home *** CD-ROM | disk | FTP | other *** search
/ Aminet 12 / Aminet 12 (1996)(GTI - Schatztruhe)[!][Jun 1996].iso / Aminet / dev / lang / HeliOS4.lha / helios_demo_disk4 / tutorials / HeliOSLanguageTutorial2.doc < prev    next >
Encoding:
Text File  |  1995-12-10  |  101.1 KB  |  2,715 lines

  1.  
  2. Topics covered in this tutorial:
  3.  
  4. * A further introduction to elementary HeliOS programming
  5. * HeliOS program structure and source code layout
  6. * Colon Definitions
  7. * HeliOS "WORDS" and the dictionary
  8. * The Dictionary memory area
  9. * A litle more about the terms "Compiling" and "Interpreting"
  10. * Computer Memory and more about the HeliOS Stack
  11. * The HeliOS stack display
  12. * Passing parameters between HeliOS Words and using Stack Diagrams
  13. * Using 8-bit, 16-Bit and 32-Bit numbers
  14. * Specifying number sizes
  15. * Converting between differently sized numbers on the stack
  16. * Using 16-Bit and 32-Bit memory addressing modes
  17. * The HeliOS Dictionary is a 16-bit addressed, 16-bit data structure
  18. * A repeated IMPORTANT warning
  19. * Converting between 16-bit and 32-bit addresses
  20. * How HeliOS specifies 16-bit and 32-bit addressing and numbers.
  21. * Using Variables
  22. * Using "Text Strings" in HeliOS programs
  23. * A very simple and useful HeliOS string handling word - "LIT$".
  24. * General INPUT and OUTPUT using HeliOS
  25. * Sending text output to the user via the screen display
  26. * A simple tutorial programming exercise
  27. * Entering and compiling our new program
  28. * Using Amiga Libraries from within HeliOS
  29. * Closing a library
  30. * Making a library call
  31. * Making a call to external assembler-generated code
  32. * General procedures for Starting and Closing programs
  33. * A typical "universal" start up program
  34. * A few simple hints on debugging
  35. * Additional reading?
  36.  
  37. -------------------------------------------------------
  38. A further introduction to elementary HeliOS programming
  39. -------------------------------------------------------
  40.  
  41. This tutorial can be regarded as a second journey over already slightly
  42. familiar ground, pointing out new perspectives and landmarks.
  43.  
  44. In some ways this second tutorial is simpler than the first, so if you did
  45. not fully grasp the previous material this new presentation may help fill
  46. in some of the gaps.
  47.  
  48. There are also some new ideas presented here, building on previous concepts
  49. and leading to a short program which can be used as a framework for all your
  50. early HeliOS programs.
  51.  
  52. HeliOS is a Forth-like language, especially in its simpler aspects, and the
  53. more sophisticated features of HeliOS build upon a central core of commands
  54. which are closely related to those defined in the popular and universally
  55. recognised fig-Forth standard.
  56.  
  57. This tutorial is concerned mainly with the use of these simple Forth-related
  58. HeliOS functions, and will give general instruction on Forth programming 
  59. concepts.  
  60.  
  61. You will also find an introduction to several of the most useful of the
  62. Amiga-specific control functions provided by HeliOS.
  63.  
  64. This is not a detailed or advanced HeliOS language lesson, and does not deal
  65. in depth with programming the Amiga operating system and hardware: however,
  66. it will take you to the point where you can start writing simple and useful
  67. programs based upon the examples given.
  68.  
  69. If you follow the introductory instructions and get the small demonstration
  70. programs working you will, by the end of this tutorial, have a sound basis
  71. for writing useful programs of your own which include text and graphics.
  72.  
  73. To help you get started with your own programs we include here a standard
  74. "start up and close down" mini-program which you can use as a general basis
  75. for all your early experimental code.  This "framework" program will enable
  76. you to open screens and windows, get user input, print text and display
  77. graphics: all the elements of simple programming in fact.
  78.  
  79. The HeliOS disks also include several quite simple source code files which
  80. will introduce various programming techniques while still being quite easy
  81. to follow.  It is easy to modify these programs with your own ideas and
  82. variations, and from there you can progress to studying the more complex
  83. examples provided.  If you feel really ambitious you may even like to try
  84. looking at and modifying the full source code for a complete program such
  85. as the HeliOS "Defender" game, which is available from Helios Software.
  86.  
  87. It may be boring in places, but even if you are familiar with Forth-type
  88. languages please read through all the introductory tutorials BEFORE trying
  89. to actually change any of the example programs provided.  This will help
  90. prevent initial frustration, because HeliOS is a very unusual language,
  91. and a certain amount of insight into how HeliOS works is necessary even
  92. for experienced Forth programmers.
  93.  
  94.  
  95. -----------------------------------------------
  96. HeliOS program structure and source code layout
  97. -----------------------------------------------
  98.  
  99. The first thing to learn is a sensible way to write and format your "source
  100. code" in such a way that it is clear to read and easy to comprehend.  Much
  101. of this is a matter of personal style, especially in a language like HeliOS
  102. which allows very free text formatting within source code.
  103.  
  104. Computer languages, like people, can only understand text written according
  105. to certain rules, and even a very free form language like HeliOS requires
  106. that you obey certain constraints.  Fortunately there are very few "rules"
  107. to learn with HeliOS and there are no artificial constraints such as "line
  108. numbering", or "strictly typed variables".
  109.  
  110. Traditional Forth did employ a quite rigid and unusual form of source code
  111. stored in special "blocks", but HeliOS allows great freedom of text layout
  112. within the framework of a few simple but necessary rules.
  113.  
  114. Some computer languages simply allow a whole program to be one single long
  115. "stream" of code, but this can be highly confusing.  The more sophisticated
  116. languages allow code to be broken down into easy-to-handle sub-sections, or
  117. "subroutines", which can in turn be logically organised in a clear and
  118. functionally efficient manner.  The latter type of language is generally
  119. referred to as a "structured language".
  120.  
  121. HeliOS programs are highly structured, and the language allows the creation
  122. of subroutines, often called "Words", which are defined using a source code
  123. construct called the "colon definition".  This name is used because each
  124. new subroutine definition starts with the colon ":" character.
  125.  
  126. Within the "colon definitions" which define your functional code, there may
  127. be used all the usual logical constructs such as "IF-ELSE-THEN", "DO-LOOP",
  128. "BEGIN-UNTIL" etc etc.  All these constructs are easy to use and allow you
  129. to create neat and easy to read logically structured code.
  130.  
  131. In effect HeliOS programming consists in defining new words which extend the
  132. language itself, and as such is a very flexible and intuitive process.  You
  133. can lay out programs in a very free way, and you may use any text editor
  134. which produces standard ASCII files, although it well generally be most
  135. convenient to use the integrated HeliOS editors because you can compile
  136. source code directly from there.
  137.  
  138. The only real rule which you must obey when writing HeliOS source code is
  139. that, as in normal human language, all words must be separated by at least
  140. one space.
  141.  
  142. Other than this "absolute" rule, everything else is a matter of personal
  143. preference, and it would be inappropriate for us to present too many
  144. guidelines.  However, there are a few general suggestions which might be
  145. useful.
  146.  
  147. Generally speaking, it is a good idea to present each small functional
  148. section of code on its own line, preferably placing the code well to the
  149. left of the page to allow room for comments on the right.
  150.  
  151. For example:
  152.  
  153.  
  154.  FORGET **CORE**       \ Clear user dictioary
  155.  
  156.  ." Here I am!"        \ Introduce myself
  157.  
  158.  WAITSPACE             \ Wait for space
  159.  
  160.  
  161. It is useful to keep comments vertically aligned where possible, and it is
  162. often worthwhile including stack comments where your code is manipulating
  163. several parameters on the stack, so that you can see easily what is going
  164. on with each line of code.
  165.  
  166. For example:
  167.  
  168.  FORGET **CORE**       \ Clear user dictioary
  169.  
  170.  40  VARIABLE WIDTH    \ Width of box to draw on screen
  171.  40  VARIABLE HEIGHT   \ Height of box to draw on screen
  172.  120 VARIABLE TOPLEFTX \ Top left corner of box X coordinate
  173.  120 VARIABLE TOPLEFTY \ Top left corner of box Y coordinate
  174.  6   VARIABLE COLOUR   \ Colour of box
  175.  
  176.  : DRAWBOX
  177.  
  178.  SCRCLR                \ Clear screen
  179.  
  180.  TOPLEFTX @ TOPLEFTY @ \ Box X and Y offsets    - - - X, Y
  181.  
  182.  DDUP                  \ Duplicate coordinates  - - - X, Y, X, Y,
  183.  
  184.  HEIGHT @ +            \ Add box height         - - - X, Y, X, Y+H
  185.  
  186.  WIDTH @ UNDER+        \ Add box width          - - - X, Y, X+W, Y+H
  187.  
  188.  COLOUR @              \ Get box colour         - - - X, Y, X+W, Y+H, C
  189.  
  190.  GFXSETAPEN            \ Set box colour
  191.  
  192.  GFXRECTFILL           \ Draw box
  193.  
  194.  WAITSPACE             \ Wait for space
  195.  ;
  196.  
  197.  DRAWBOX               \ Test our new word
  198.  
  199.  
  200. It really is up to you how you lay things out, but do consider the fact
  201. that your code needs to be readable and easy to debug, which in most cases
  202. is achieved best by using a regular, carefully formatted, and well spaced
  203. layout.
  204.  
  205.  
  206. -----------------
  207. Colon Definitions
  208. -----------------
  209.  
  210. The colon definition allows you to create a "subroutine" consisting of a
  211. combination of commands and give a name to the resulting functional unit.
  212.  
  213. The new "definition", or "Word", can then be used by simply entering its 
  214. name in later source code.
  215.  
  216. You have actually created a new operator which is just as much a part of
  217. the language as the initial HeliOS Core vocabulary functions.
  218.  
  219. The start of a new subroutine is designated by a colon, and, after the code
  220. specifying what the new word does, we end the definition with a semicolon.
  221.  
  222. Look at the example below:
  223.  
  224.   : NEWWORD   |<--------definition-------->| ;
  225.  
  226. Here you can see the colon and the semicolon with the definition placed in
  227. between.
  228.  
  229. Note that immediately following the colon is the word NEWWORD, and, as you
  230. may have guessed, this is the name of our new subroutine.
  231.  
  232. Remember that YOU choose the name of the new function: it can be anything
  233. you like, but always try to use distinctive and descriptive terms to make
  234. your code more comprehensible to you.  If you choose names carefully your
  235. code can be made almost as readable as English language. On the other hand
  236. it is very easy to write very incomprehensible code indeed......
  237.  
  238. A lot of your HeliOS code will consist of the use of the colon definition,
  239. so you will soon become very familiar with it: there are plenty of examples
  240. elsewhere in the tutorials.
  241.  
  242.  
  243. ---------------------------------
  244. HeliOS "WORDS" and the dictionary
  245. ---------------------------------
  246.  
  247. HeliOS subroutines are called "WORDS", the total set of words available is
  248. called the "VOCABULARY", and the place where all the words are stored in
  249. the computer's memory is called the "DICTIONARY".
  250.  
  251. Because HeliOS source code is concerned with very "linguistically" oriented
  252. activities, and because the definition and use of language is a very vital
  253. part of HeliOS, the term "WORD" tends to become a rather overworked part of
  254. HeliOS terminology.  This mainly stems from traditional Forth usage.
  255.  
  256. Historically Forth programmers have always referred to subroutines and
  257. their definitions as 'WORDS', but this can be confusing because the term
  258. WORD was used in several different ways in Forth computing parlance -
  259.  
  260.   1. It defines a quantity of memory - 2 bytes or 16 bits.
  261.  
  262.   2. It is used to refer to the basic functional units of the Forth
  263.      Language in terms of WHAT THEY DO operationally.
  264.  
  265.   3. It is used in the English Language sense to refer to the actual NAME
  266.      of the subroutine - the actual letters which you type to define it.
  267.  
  268. A little care has to be taken, when you are first starting with HeliOS, or
  269. any other FORTH based language, to understand the context in which the word
  270. "WORD" is being used!
  271.  
  272. All the commands and subroutines that HeliOS uses, including both your own
  273. subroutines and predefined HeliOS word definitions are stored in the HeliOS
  274. "dictionary".
  275.  
  276. As each new definition is added, the free space in the HeliOS dictionary is
  277. reduced. This space has a fixed limit, and you can always see how much room
  278. is left in the dictionary by looking at the status display at the top left
  279. of the HeliOS screen.  When the dictionary is full you can write no more
  280. code, but since HeliOS compiled code is VERY compact this would mean that
  281. you had already written a very large program indeed.
  282.  
  283. You can list the current words in the Dictionary simply by typing "VLIST" at
  284. the command line (described later), or using one of the menu options in the
  285. Interpreter "HeliOS" menu.
  286.  
  287. It is important to understand how the dictionary works because the general
  288. compilation method used by HeliOS is quite unlike that of most other Amiga
  289. languages.
  290.  
  291.  
  292. Basically this is what happens -
  293.  
  294.   1. You create a subroutine by typing in one or more lines of source code
  295.      in the form of a named colon definition.
  296.  
  297.   2. When the source code is interpreted, or compiled, the executable code
  298.      relating to your new word is stored in the dictionary in a form which
  299.      can later be "understood" and acted upon by the computer.
  300.  
  301.   3. The name you gave the new word is stored SEPARATELY in a special list,
  302.      rather like an index, which allows the word to be found and used later
  303.      merely by entering its name.
  304.  
  305.  
  306.      Important Note:
  307.  
  308.      HeliOS is very different from traditional Forth in the way that it
  309.      stores word names in a separate list.  If you are a seasoned Forth
  310.      programmer, or have a book on traditional Forth, you should read and
  311.      remember the following note, as it will beneficially effect your whole
  312.      programming style.
  313.  
  314.      When a HeliOS program is finally run the list of word names is no
  315.      longer needed.  This means that when you produce completed stand-
  316.      alone programs the list of names can be omitted.  If you think about
  317.      it you will see that this is very useful, because it means that you
  318.      can use long descriptive names for your subroutines without having
  319.      to worry about them cluttering up your program later.
  320.  
  321.      This may seem very obvious, but traditional Forth actually stored the
  322.      word names permanently within the program code and you may find books
  323.      which advise you to use short names for this reason.
  324.  
  325.      Using HeliOS you can relax and use word names as long as you like.
  326.  
  327.      So just try to make your function names useful and descriptive.
  328.  
  329.  
  330. Every time these three steps are performed the compiled "code" is added to
  331. the dictionary.  If you recompile a subroutine and do not change its name,
  332. any earlier version(s) remain still stored in the dictionary, and will be
  333. left in place but superseded by the latest addition.
  334.  
  335. This means that your latest word definition will always be the one used in
  336. response to typing the subroutine name, but the "old" definitions will still
  337. be there lower in the dictionary.  If you use the word "FORGET" to clear
  338. the very latest definition with a certain name from the dictionary, any
  339. previous definition with that name will now once again be available.
  340.  
  341. During a typical session you may well work on a program by continually
  342. recompiling and testing code.  If you make no attempt to clear previous
  343. additions to the dictionary then it will be filled quite quickly with
  344. multiple definitions.  This is not dangerous, but is slightly messy and
  345. untidy to leave old definitions piling up over a long period: for this
  346. reason you should learn how to use the "FORGET" command.
  347.  
  348. The FORGET command allows you to forget any specified definition, and in
  349. fact you should be careful because it also, at the same time, gets rid of
  350. any (and every) word compiled SINCE that specified definition.
  351.  
  352. Thus:
  353.  
  354. : TEST1 ." Hello" ;
  355. : TEST2 ." Hello there" ;
  356. : TEST3 ." Hello there!" ;
  357. : TEST4 ." BOLDON Hello there!" ;
  358.  
  359. FORGET TEST3
  360.  
  361. would leave everything alone up to and including the TEST2 definition, but
  362. erase everything compiled after this point (TEST3 and TEST4).
  363.  
  364. The dictionary can be totally cleared back to the fixed CORE dictionary
  365. (the set of standard words which are available at startup) by using the
  366. expression:
  367.  
  368.  FORGET **CORE**
  369.  
  370. Placing this at the start of a program source code file ensures that you
  371. can keep recompiling the source code without subroutine definitions being
  372. duplicated and without the dictionary gradually being filled up.
  373.  
  374. We will from now on call the basic set of HeliOS commands, which is ALWAYS
  375. available, the CORE dictionary (or vocabulary), and all the subroutines
  376. defined in your own code as the USER dictionary (or vocabulary).
  377.  
  378. Here are three command words to list the vocabularies:
  379.  
  380. CVLIST -> List the CORE vocabulary
  381. UVLIST -> List the USER vocabulary
  382. VLIST  -> List the CORE vocabulary followed by the USER vocabulary
  383.  
  384. You can also use the equivalent interpeter menu options.
  385.  
  386. --------------------------
  387. The Dictionary memory area
  388. --------------------------
  389.  
  390. The HeliOS Dictionary is a 64k reserved memory area with some important
  391. special properties:
  392.  
  393. 1. It is where all HeliOS word definitions are stored.
  394.  
  395. 2. It is where all HeliOS variables are stored.
  396.  
  397. 3. It is limited in size and cannot be extended.
  398.  
  399. 4. It can be addressed using 16-bit or 32-bit addressing (See later).
  400.  
  401. 5. It is located in Amiga FAST memory (where this is available).
  402.  
  403. The Dictionary memory space is an important and limited commodity, and you
  404. must be careful not to fill this memory with data which could legitimately
  405. be stored elsewhere, especially if you are writing large programs.
  406.  
  407. There is a Dictionary free space readout on the top left of the HeliOS
  408. status display, and you should keep a careful watch on this at all times.
  409.  
  410. In general it is possible to make use of the Dictionary memory space for
  411. all kinds of data storage, and this has the advantage that no specific
  412. memory allocation need be made, and there is no deallocation to do later.
  413.  
  414. The Dictionary memory also has the advantage that it can be addressed using
  415. 16-bit numbers (see later), which reduces program size and simplifies much
  416. HeliOS stack manipulation.
  417.  
  418. If you are writing small programs, where Dictionary space is plentiful, it
  419. is a good idea to use the Dictionary memory for as much of your data storage
  420. as possible.
  421.  
  422. However, if your program is quite large, and the code itself requires a lot
  423. of Dictionary space, you will need to conserve Dictionary memory as much as
  424. possible.  In these circumstances you will probably find it necessary to
  425. allocate external memory wherever possible for your data storage, leaving
  426. as much of the Dictionary space free as possible.
  427.  
  428.  
  429. -----------------------------------------------------------
  430. A litle more about the terms "Compiling" and "Interpreting"
  431. -----------------------------------------------------------
  432.  
  433. This short section of the tutorial is a small "brain teaser" which will
  434. help prepare the ground for further revelations later.  Do not dwell too
  435. long on this slightly obscure topic, but bear in mind the hints given here
  436. when reading other sections of the tutorials.  Later we will go into this
  437. subject in greater depth, and everything will become clearer when you have
  438. learned more about HeliOS programming in general.
  439.  
  440. First, a little "conventional wisdom".......
  441.  
  442. The text which contains the program instructions you wish to give to the
  443. computer is called "source" code, because it is the "starting" point for
  444. a translation process.  This translation produces the actual "executable"
  445. code which is executed by the computer's CPU (central processing unit).
  446.  
  447. The process of producing machine-readable CPU executable code from the
  448. human-readable source code is known as "compiling".  Strictly speaking,
  449. "compiling" is the term used to describe the process whereby the source
  450. code for a program is converted to executable code in the form of a file
  451. which can be "run" or "executed" later.
  452.  
  453. Some computer languages, rather than compiling source code into executable
  454. code as a whole, translate and execute each bit of source code as they go.
  455. This process is called "interpreting".  The latter languages run programs
  456. very slowly because of the inefficient on-the-fly interpretation process.
  457. They do, however, have the advantage that you can "try out" code at once
  458. to see how it works: an "interpretive" language gives an instant response.
  459.  
  460. The pure "compiler" languages produce much faster final code, but in turn
  461. they suffer from a rather serious disadvantage in that the process of
  462. compilation is quite involved and time consuming.  This means that the
  463. programmer's task of compiling, testing, rewriting, and recompiling can
  464. be a very slow and non-interactive (often frustrating) occupation.
  465.  
  466. HeliOS is a "compiler", but it also has an "interpretive mode" as well,
  467. which is a good thing because it means that you can create fast compiled
  468. programs AND test them interactively as you go.  This feature of HeliOS
  469. alone is a very good reason for using it as a "learning" language, and
  470. the efficiency with which it both "interprets" and "compiles" lifts it
  471. above any other language on the Amiga.
  472.  
  473. Now for some slightly disturbing "unconventional wisdom".......
  474.  
  475. Compiling and interpreting are generally (and over-simplistically) regarded
  476. as two separate "modes of operation", but you should be aware, even at this
  477. early stage, that the operation of HeliOS is not quite this simple.
  478.  
  479. Actually, you could say that all compilation is performed by the HeliOS
  480. interpreter, or that interpretation is performed by the HeliOS compiler!
  481.  
  482. This is all a matter of perspective, because the terms used are designed
  483. to be applied to "conventional" standardised computer operations and not
  484. to the rather subtle and ambivalent way in which HeliOS works.
  485.  
  486. This can all become a little confusing, but you need to be aware that when
  487. it is "interpreting" a sequence of instructions HeliOS frequently changes
  488. from interpretation to compilation depending on what command is being
  489. processed.
  490.  
  491. What is worse, in fact, is that WHILE HeliOS is "compiling" any word it is
  492. always, even AT THE SAME TIME "interpreting" the function which is doing the
  493. compilation!  HeliOS is simultaneously compiling AND interpreting!
  494.  
  495. This situation relates to the fact that HeliOS is a language which uses its
  496. own functions to recreate and extend itself.
  497.  
  498. At any "clock" time, or real-world instant in time, HeliOS can be said to
  499. be running several functions at once, some of which are "compiling" and
  500. others of which are "interpreting".  Furthermore, these words are not even
  501. processed "in parallel", but as threaded, or "nested", control structures
  502. through which the computer CPU makes its way sequentially.
  503.  
  504. It is important to realise that in HeliOS the processes of compilation and
  505. interpretation are under direct and immediate programmed control, and that
  506. as your source code is being processed some functions are interpreted and
  507. executed at once, while others are being compiled.
  508.  
  509. Here is an example showing why you need to take care.
  510.  
  511. The word HEX changes the HeliOS numeric base to hexadecimal, and DECIMAL
  512. changes the numeric base to decimal, which is the default setting.
  513.  
  514. Typing
  515.  
  516. DECIMAL FF .
  517.  
  518. will generate an error, since "FF" is not a decimal number.
  519.  
  520. On the other hand, typing
  521.  
  522. HEX FF .
  523.  
  524. will not generate an error, since "FF" can now be interpreted as a legal
  525. hexadecimal number.
  526.  
  527. Try them at the command line.
  528.  
  529. Now try this word definition:
  530.  
  531. : TEST   HEX FF .  ;
  532.  
  533. Highlight the above line and use "Amiga-e": you will get an error!
  534.  
  535. Can you see why?
  536.  
  537. The reason for the error is that HeliOS actually COMPILES the word HEX,
  538. and does not execute it, so the numeric base is still DECIMAL when the
  539. word "FF" is encountered.
  540.  
  541. HeliOS then tries to INTERPRET the string "FF" (as a number), before it
  542. compiles it as part of the definition of TEST, and fails because "FF" is
  543. not a legal decimal numeric value.
  544.  
  545. What can we do about this?
  546.  
  547. Here is the solution:
  548.  
  549. : TEST [ HEX ] FF . ;
  550.  
  551. What we have done here is to use the special words "[" and "]" to force the
  552. word "HEX" to be interpreted and executed at once rather than compiled as
  553. part of the colon definition.
  554.  
  555. Note that these are HeliOS words (not just square brackets around HEX) and
  556. require spaces on each side of the "[" and "]".
  557.  
  558. Let us examine just what is happening here.
  559.  
  560. The word ":" initially forces HeliOS to switch into "compile" mode while
  561. processing the code up to the terminating ";".
  562.  
  563. As we know, normally this would cause the word HEX to be compiled.
  564.  
  565. The word "[" forces HeliOS to switch back temporarily into "interpret" mode.
  566.  
  567. Now the word HEX will be interpreted at once, changing the numeric base.
  568.  
  569. The word "]" forces HeliOS to return to "compile" mode.
  570.  
  571. The colon definition then continues compiling up to the final ";" as usual.
  572.  
  573. Now try the new version of "TEST": it will work correctly without error.
  574.  
  575. Interesting isn't it!
  576.  
  577. You will learn more about this later...........
  578.  
  579.  
  580. -----------------------------------------------
  581. Computer Memory and more about the HeliOS Stack
  582. -----------------------------------------------
  583.  
  584. Memory is the basic storage medium for program code and data.
  585.  
  586. Memory can be thought of as a series of cells, each of which can hold a
  587. numerical value, and the way in which each value is interpreted is largely
  588. determined by the code within your program.
  589.  
  590. HeliOS uses a special device called a STACK, which is actually just a small
  591. organised subsection of the large general memory pool.  Rather than being
  592. randomly accessed in any order, the stack is accessed sequentially like a
  593. pile of boxes (containing information), or a deck of cards.
  594.  
  595. Data is, in general, placed on the top of the stack and then removed when
  596. it is needed later.
  597.  
  598. As more and more items are stored on the stack it grows in size, and the
  599. oldest items, those placed on the stack first, are left at the bottom.
  600.  
  601. The HeliOS stack is employed to store sets of numbers which are going to be
  602. used almost at once by other subroutines, and can be regarded as a quick
  603. temporary store.  It can also be looked upon as a "channel" of information
  604. between sequential operations.  Typically one operation will put a number
  605. onto the stack, and the next will take the number off the stack and use it.
  606. You can think of it almost as a type of "messenger" carrying data between
  607. different parts of your program: a kind of "dumb waiter".
  608.  
  609. Many HeliOS words, including your own program subroutines, look for and
  610. return values on the stack, and this process is called "parameter passing".
  611.  
  612. Many would-be Forth programmers are initially terrified of using the stack
  613. because they have never used such a thing before and have perhaps used other
  614. languages which employ NAMED VARIABLES rather than a stack.
  615.  
  616. Actually you will soon see that the stack is ridiculously easy to use and
  617. gives you a lot more programming power than the restrictive use of variables
  618. for all parameter passing.  In HeliOS you can use the stack or you can use
  619. named variables, or both together: so you have more power and more choice.
  620.  
  621. HeliOS provides a large number of words for manipulating the stack, and
  622. these should be learned as soon as possible - they will all soon become
  623. familiar since they are in constant use in ALL your HeliOS code.  This is
  624. because you are constantly needing to adjust the position of data items
  625. on the stack, as well as adding, deleting, and duplicating items.
  626.  
  627. Traditional Forth had just a few stack control words, and managed any more
  628. complex operations needed by combining many of these simple words together.
  629. Because the names used in Forth for stack operators are short and cryptic,
  630. complicated combinations of them are very unreadable.  Not only this, but
  631. use of a lot of generalised words to do a job rather than one specific word
  632. is very inefficient.  This was THE major problem with early Forth systems.
  633.  
  634. This problem of "stack control" is one of the weakest parts of traditional
  635. Forth, and is largely responsible for Forth code getting a reputation for
  636. being quite unreadable.  This is a shame, because Forth was potentially the
  637. most "readable" of all computer languages, and it was largely the limited
  638. stack control vocabulary of early Forth systems which caused the difficulty.
  639.  
  640. HeliOS has removed the necessity for worry over stack manipulation by
  641. providing the most complete set of specialised words ever available in a
  642. Forth-type language.  Try to gradually incorporate more and more of these
  643. words into your knowledge of HeliOS, so that you can use just the right
  644. specific word for the job rather than a series of less appropriate ones.
  645.  
  646. HeliOS has adopted another totally new philosophy which departs from Forth
  647. tradition: all the stack control words in HeliOS are machine coded for
  648. maximum speed, so all are equally fast and efficient.
  649.  
  650. We have dwelt perhaps overmuch on the stack, because the use of the stack
  651. will be really important throughout all of your HeliOS programming.  The
  652. concept of always using the minimum of stack control words throughout your
  653. code is VERY important if your HeliOS programs are to be readable, easily
  654. maintained, and fast in operation.
  655.  
  656. Before leaving this important subject, here is a very quick practical
  657. example of stack manipulation so that you can see what it is all about.
  658.  
  659. Take a stack with four numbers on it:      1,  2,  3,  4
  660.  
  661. Imagine that the "4" is at the top, and the "1" is at the bottom.
  662.  
  663. Suppose that we want to duplicate the third number from the top and place
  664. a copy of it on the top of the stack.
  665.  
  666. (Believe it or not, this sort of thing is quite commonly required!)
  667.  
  668. So we need to operate on our initial stack to get:  1,  2,  3,  4,  2
  669.  
  670. Let us assume that we have four stack operators:
  671.  
  672.    DUP           - this duplicates the number on top of the stack
  673.                    eg.  1, 2, 3, 4   ->   1, 2, 3, 4, 4
  674.  
  675.    SWAP          - this exchanges the top two stack items
  676.                    eg.  1, 2, 3, 4   ->   1, 2, 4, 3
  677.  
  678.    DSWAP         - this exchanges the top two "double" stack items
  679.                    eg.  1, 2, 3, 4   ->   3, 4, 1, 2
  680.  
  681.    ROT           - this REMOVES the third number on the stack and
  682.                    puts it onto the top
  683.                    eg.  1, 2, 3, 4   ->   1, 3, 4, 2
  684.  
  685. How do we solve our simple problem?
  686.  
  687. Why not try it as an exercise on paper?
  688.  
  689. We could do the following:                      1, 2, 3, 4
  690.  
  691.                                    ROT   ->
  692.                                                 1, 3, 4, 2
  693.  
  694.                                    DUP   ->
  695.                                                 1, 3, 4, 2, 2
  696.  
  697.                                    ROT   ->
  698.                                                 1, 3, 2, 2, 4
  699.  
  700.                                    DSWAP ->
  701.                                                 1, 2, 4, 3, 2
  702.  
  703.                                    ROT   ->
  704.                                                 1, 2, 3, 2, 4
  705.  
  706.                                    SWAP  ->
  707.                                                 1, 2, 3, 4, 2
  708.  
  709. Success!  We did it! This way is slow, but it DOES work.
  710.  
  711. (Actually it can be done quicker than this.  Can you manage it?)
  712.  
  713.  
  714. But look......we have the following series of operators:
  715.  
  716.   "ROT DUP ROT DSWAP ROT SWAP"
  717.  
  718. This is horrible to read, and even worse to debug when combined with a lot
  719. of other similar sequences.  It is also very time consuming to compile and
  720. execute, since it takes SIX words to do one simple job.  If we could do
  721. this operation in ONE word we should have SIX times better code - it is
  722. as simple as that.
  723.  
  724. HeliOS would do the following in one word - and it would be a very fast
  725. internally machine coded word too.
  726.  
  727. HeliOS would say:                         1, 2, 3, 4
  728.  
  729.                              3PICK ->
  730.  
  731.                                           1, 2, 3, 4, 2
  732.  
  733.  
  734. So we have used the special operator "3PICK" = "pick out the third item"
  735.  
  736. We have written a program which compiles AND runs at least SIX times faster
  737. than the first method.
  738.  
  739. This kind of thing is fundamental to good HeliOS programming, and you will
  740. constantly come up against coding tasks exactly like the above example.
  741.  
  742.  
  743. ------------------------
  744. The HeliOS stack display
  745. ------------------------
  746.  
  747. To help you get accustomed to the working of the stack, HeliOS has a
  748. permanent stack display at the top of the Interpreter window.
  749.  
  750. Try doing a few calculations and manipulations like the examples above
  751. and watch the stack display.  This will soon give you a feeling for how
  752. the HeliOS stack works, because seeing the numbers change in the set of
  753. cells displayed graphically on screen is an excellent aid in visualising
  754. stack operations.
  755.  
  756.  
  757. ----------------------------------------------------------------
  758. Passing parameters between HeliOS Words and using Stack Diagrams
  759. ----------------------------------------------------------------
  760.  
  761. Let us take, as a simple example, the HeliOS Word "FPENSET".
  762.  
  763. This word sets the foreground text pen colour, which is simply a number.
  764.  
  765. On a four colour screen text could be displayed in colour 0, 1, 2 or 3.
  766.  
  767. Let us assume we are starting from an empty stack.
  768.  
  769. Our word FPENSET needs to know what colour we want it to use, and this is
  770. done very simply in HeliOS by passing the colour number as follows:
  771.  
  772.                       1 FPENSET            for  "colour 1"
  773.  
  774.           or          3 FPENSET            for  "colour 3"
  775.  
  776.  
  777. Here the "parameter", the colour number, is "1" (or "3"), and is written
  778. in your source code as a simple number preceding the word FPENSET.
  779.  
  780. This looks very natural and simple, and indeed this simplicity is a very
  781. good feature of HeliOS, but a little more is happening than is apparent.
  782.  
  783. What actually happens is that the number "1" is stored on the stack until
  784. it is used by FPENSET, which leaves the stack empty.
  785.  
  786. This situation can be represented by a device called a "stack diagram",
  787. which is simply a means of representing textually what happens to values
  788. on the stack during the operation of a HeliOS Word.
  789.  
  790. You will see stack diagrams used throughout the HeliOS tutorials, and in
  791. particular they are a vital part of all Dictionary Word definitions.
  792.  
  793. In the case cited above we would have a stack diagram as follows:
  794.  
  795.                      ( n - - - )
  796.  
  797. The "n" represents the colour number which the word FPENSET expects to
  798. find placed on the stack.
  799.  
  800. The three "-" signs signify the "point in time" in the computing process
  801. when FPENSET does its work.
  802.  
  803. The fact that there is no number afterwords means that FPENSET actually
  804. uses internally and removes its single parameter, leaving nothing on the
  805. stack itself.
  806.  
  807. The parameter to be passed to the subroutine is stored temporarily on
  808. the stack, the subroutine then removes it and, in this case, returns
  809. with the stack clear.
  810.  
  811. This type of method is crucial to HeliOS operation.
  812.  
  813. Several parameters can be passed to subroutines via the stack, as you will
  814. see in the examples given below.
  815.  
  816. The word GFXRECTFILL, for example, uses four parameters denoting the corners
  817. of a box to draw a filled rectangle.
  818.  
  819. e.g.
  820.  
  821. SCRCLR 6 GFXSETAPEN     100 100 120 120 GFXRECTFILL    WAITSPACE SCRCLR
  822.        ^                ^^^^^^^^^^^^^^^
  823.     Single parameter    Four parameters
  824.  
  825. Many subroutines use the stack to return parameters, and your program
  826. must constantly keep track of the stack to ensure that this process of
  827. passing parameters is kept in order.
  828.  
  829. The HeliOS words used to make ordinary arithmetic calculations all get
  830. their parameters from the stack, operate on them, and then return the
  831. result of the calculation on the stack.
  832.  
  833. In a simple addition two parameters are needed, and the result, which
  834. is a single parameter, is returned on the stack -
  835.  
  836.      3 5 +   add two numbers 3 and 5, leaving the result on the stack
  837.  
  838.      .       display on screen the value on the stack ( the "result" )
  839.  
  840. The stack diagrams of these two words would be:
  841.  
  842.     "+"       ( n1  n2  - - - n3 )
  843.  
  844.     "."       ( n3  - - - )
  845.  
  846.  
  847. --------------------------------------
  848. Using 8-bit, 16-Bit and 32-Bit numbers
  849. --------------------------------------
  850.  
  851. A computer deals with binary numbers, which are really just like sequences
  852. of simple two-state "on or off" switches.  These switches are each said to
  853. contain one "bit" of information and can only represent the numbers 1 and 0.
  854.  
  855. A single cell of memory contains an 8-bit number, which is a collection of
  856. 8 bits (or binary switches), and is called a "byte".  This can represent a
  857. decimal number of up to "255", which is still a rather small unit of data.
  858.  
  859. Because a byte is such a small "chunk" of information, we often use a much
  860. larger unit of 16-bits, or 2-bytes, which we call a "word".
  861.  
  862. Above this we have 32-bit numbers which are 2 "words" or 4 bytes in length,
  863. and these are often referred to as "long" or "longwords".
  864.  
  865. So....the data which we store is usually in the form of 1, 2, or 4 byte
  866. numbers.
  867.  
  868.  
  869. -----------------------
  870. Specifying number sizes
  871. -----------------------
  872.  
  873. You will learn a lot more about numbers later, but it is important to know
  874. that HeliOS deals largely with the 3 standard number sizes which are defined
  875. in terms of their width in binary bits.
  876.  
  877. We have:
  878.  
  879. 8-bits  = 1 byte
  880. 16-bits = 2 bytes = 1 word (in HeliOS this is called a "single number")
  881. 32-bits = 4 bytes = 1 longword  (in HeliOS this is called a "double number")
  882.  
  883. HeliOS refers to a 16-bit number as a "single number" because most HeliOS
  884. internal functioning runs in terms of 16-bit numbers, and a single stack
  885. cell is always 16-bits in size.
  886.  
  887. Thus, any ordinary number which you type, in a program or at the command
  888. line, will be interpreted by HeliOS as a 16-bit number.
  889.  
  890. What, then, do we do to enter and use "bytes" or "longwords"?
  891.  
  892. Well, as far as "bytes " are concerned, you treat them exactly like 16-bit
  893. numbers: in fact HeliOS stores single byte data on the stack as a 16-bit
  894. number, even though this leaves one byte of the stack cell unused.  There
  895. are functions to handle byte length numbers once they are "on the stack",
  896. but as far as number entry and stack storage is concerned a single byte data
  897. value is treated just like a 16-bit number.
  898.  
  899. Longwords, or double numbers, are somewhat different, because these numbers
  900. actually take up 2 stack cells each.  This means that HeliOS has to be told
  901. somehow, when you type in a number, that this is a double number and must
  902. be stored in 32-bit (4 byte) format.
  903.  
  904. When you want to enter a number as a 32-bit double number you have to write
  905. the number in a special form so that the HeliOS interpreter can treat this 
  906. number appropriately.  This is done by including a "." character within the 
  907. numeric expression.
  908.  
  909. Here then, is a VERY important rule:
  910.  
  911. *  32-bit numbers must be entered with a "." character ANYWHERE within the
  912.    numeric expression.
  913.  
  914.    (This rule is actually a slight simplification, but it will suffice for
  915.    now: we will go into more detail later.)
  916.  
  917. For example, here are some ways of entering "double" 32-bit numbers:
  918.  
  919. 123.   .123    1.23   12.3   -.123   -1.23
  920.  
  921. Note that the "." character merely tells HeliOS that this is to be treated
  922. as a 32-bit number, and is NOT necessarily a decimal point indicator.
  923.  
  924. HeliOS does actually have a mechanism for reading decimal numbers, and it is
  925. possible to use the decimal point specifying the 32-bit number as a decimal
  926. place indicator.  However, this is a more advanced topic and will be dealt
  927. with in a later tutorial.
  928.  
  929.  
  930. ---------------------------------------------------------
  931. Converting between differently sized numbers on the stack
  932. ---------------------------------------------------------
  933.  
  934. Take careful note of the information in this section, since you will need
  935. to use it very often.
  936.  
  937. Signed 16-bit data values can easily be converted from single (16-bit) to
  938. double (32-bit) size using the HeliOS word "S>D" ("single-to-double").
  939.  
  940. However, signed 32-bit values can only be converted from double to single
  941. safely if they are less than 16-bit in numerical size: otherwise there
  942. will obviously be a truncation effect.
  943.  
  944. Provided that a 32-bit signed number is of appropriate size, it may be
  945. converted to 16-bit size by simply dropping the top 16-bit cell from the
  946. stack.
  947.  
  948. For example:
  949.  
  950. -32  as a 16-bit number is stored on the stack as one cell : -32
  951.  
  952. -32. as a 32-bit number is stored on the stack as two cells: -32 -1
  953.  
  954. Dropping the -1 gives us just -32 on the stack, which is what we wanted.
  955.  
  956. (Note that the top 16-bit stack cell holds the upper 16 bits of the 32-bit
  957. number, and see the documentation on signed and unsigned number represention
  958. in "Tutorial4" for an explanation of why this top cell is a 16-bit "-1".)
  959.  
  960. Try this in the interpreter until you see clearly what is happening.
  961.  
  962. Unsigned single numbers can be converted to double numbers by simply adding
  963. a zero to the stack, since this zero represents the high word of the new
  964. 32-bit value.
  965.  
  966. In a similar way to the previous example with signed numbers, unsigned
  967. 32-bit numbers can sometimes (depending on number size) be converted to
  968. 16-bit values by simply dropping the top stack cell.
  969.  
  970. For example:
  971.  
  972. 32  as a 16-bit number is stored on the stack as one cell : 32
  973.  
  974. 32. as a 32-bit number is stored on the stack as two cells: 32 0
  975.  
  976. You can see from this how the conversion process in each direction would
  977. work.
  978.  
  979. Again, you can experiment in the interpreter until you see clearly what is
  980. happening.
  981.  
  982.  
  983. -----------------------------------------------
  984. Using 16-Bit and 32-Bit memory addressing modes
  985. -----------------------------------------------
  986.  
  987. Computers use numeric values to define positions in memory, often called
  988. memory "addresses", so that they know where to store and fetch information.
  989.  
  990. On a machine like the Amiga, memory must normally always be "addressed" by
  991. 32-bit, or 4-byte "long" numbers.
  992.  
  993. A 32-bit address is often referred to as a "long" address, or a "longword"
  994. address.
  995.  
  996. HeliOS uses a little "trick" to avoid the use of these very large numbers
  997. all the time.  It defines addresses within the HeliOS dictionary as 16-bit
  998. numbers and "internally" adds a further number (or "base address") to these
  999. addresses to get the true 32-bit address.
  1000.  
  1001. Remember that HeliOS can actually use 16-bit addressing or 32-bit addressing
  1002. depending on whether an address is in dictionary memory space.
  1003.  
  1004. Note that:
  1005.  
  1006. * 16-bit addressing can only be used for addresses within dictionary space.
  1007.  
  1008. * 32-bit addressing can be used for addresses within ANY memory space.
  1009.  
  1010. * Double word 32-bit addressing specifies a memory location directly as one
  1011.   large 4 byte long number, and this mode of addressing must ALWAYS be used
  1012.   in conjunction with Amiga library calls.
  1013.  
  1014.  
  1015. ------------------------------------------------------------------
  1016. The HeliOS Dictionary is a 16-bit addressed, 16-bit data structure
  1017. ------------------------------------------------------------------
  1018.  
  1019. What does this "imposing" statement mean?
  1020.  
  1021. To keep things simple for now we should just point out that HeliOS uses
  1022. 16-bit numbers for its standard mode of operation.
  1023.  
  1024. Numbers on the stack are normally stored as 16-bit "cells".
  1025.  
  1026. HeliOS stores 8-bit numbers on the stack also in a 16-bit cell, but ignores
  1027. the top byte of the number.
  1028.  
  1029. HeliOS stores 32-bit numbers on the stack as a "double" cell.
  1030.  
  1031. A 32-bit number can sometimes conveniently be regarded as being stored on
  1032. the HeliOS stack as two 16-bit cells, but there are many HeliOS commands
  1033. which treat it conveniently and simply as a single unitary 32-bit entity.
  1034.  
  1035. A 16-bit number is often referred to in HeliOS as a "single number".
  1036.  
  1037. A 32-bit number is often referred to in HeliOS as a "double number".
  1038.  
  1039. As well as using 16-bit data items as "standard", all memory addressing
  1040. within the HeliOS dictionary memory space is usually specified by 16-bit
  1041. numbers also (although any 16-bit HeliOS address can also be specified as
  1042. a 32-bit address if required).
  1043.  
  1044. In general then, HeliOS, like traditional Forth, is largely concerned in
  1045. its internal operations with 16-bit numbers.
  1046.  
  1047.  
  1048. ----------------------------
  1049. A repeated IMPORTANT warning
  1050. ----------------------------
  1051.  
  1052. All normal Amiga addressing is 32-bit!
  1053.  
  1054. 16-bit addressing is ONLY used to specify memory addresses within the main
  1055. HeliOS dictionary. 
  1056.  
  1057. Remember always that this 16-bit addressing technique specifies a memory 
  1058. location as an offset from a point of reference which is the start of the 
  1059. HeliOS dictionary.
  1060.  
  1061.  
  1062. ----------------------------------------------
  1063. Converting between 16-bit and 32-bit addresses
  1064. ----------------------------------------------
  1065.  
  1066. Here are two HeliOS command words which translate between 16-bit and 32-bit
  1067. addressing for any addresses within the HeliOS dictionary:
  1068.  
  1069. W>L ( a1 - - - l1 ) -> Converts a 16-bit address to a 32-bit address
  1070.  
  1071. L>W ( l1 - - - a1 ) -> Converts a 32-bit address to a 16-bit address
  1072.  
  1073. Note that you MUST NOT attempt to convert 32-bit addresses which are not
  1074. located within the HeliOS Dictionary space to 16-bit addresses.
  1075.  
  1076.  
  1077. --------------------------------------------------------------
  1078. How HeliOS specifies 16-bit and 32-bit addressing and numbers.
  1079. --------------------------------------------------------------
  1080.  
  1081. Addressing can be very confusing and people often get mixed up with 16
  1082. and 32 bit data values and 16 and 32 bit addresses.  To avoid confusion
  1083. when using these differing quantities we need to use a regular notation
  1084. and to keep a clear mental picture of just what all these different types
  1085. of numbers represent.
  1086.  
  1087. HeliOS uses a helpful standard form of notation, like this:
  1088.  
  1089.  1. Word names have a "D" prefix when referring to double 32-bit data
  1090.  
  1091.  2. Word names have an "L" suffix when referring to long 32-bit addressing
  1092.  
  1093.  
  1094. ---------------
  1095. Using Variables
  1096. ---------------
  1097.  
  1098. While HeliOS uses the stack for most of its "short term" parameter passing
  1099. operations, ordinary memory can be used for data storage on a more long
  1100. term basis.  Languages like BASIC and PASCAL use named variables to access
  1101. the memory in which the data is stored without involving the programmer
  1102. with the actual "physical" memory address, or indeed with "stacks".
  1103.  
  1104. HeliOS can do the same thing if required, and while the stack is much more
  1105. efficient for most parameter passing (and gives HeliOS a significant speed
  1106. advantage), there are many occasions where it is best to use variables.
  1107.  
  1108. A variable can be created using the word VARIABLE and data can be moved in
  1109. and out using the two HeliOS words "!" (which is pronounced "store") and @
  1110. (which is pronounced "fetch").
  1111.  
  1112. These two words operate very simply on a standard HeliOS 16-bit variable or
  1113. indeed upon any 16-bit addressed memory within the HeliOS dictionary.
  1114.  
  1115. Note that there are also variations on these simple "fetch" and "store"
  1116. functions which allow you to operate on different data sizes and 32-bit
  1117. memory addresses.
  1118.  
  1119. For example:
  1120.  
  1121. C! C!L C@ C@L   -> Operate on 8-bit data
  1122.  !  !L  @  @L   -> Operate on 16-bit data
  1123. D! D!L D@ D@L   -> Operate on 32-bit data
  1124.      ^      ^
  1125.      The "L" signifies 32-bit memory addressing.
  1126.  
  1127. There are many more memory accessing functions within HeliOS, and the main
  1128. Dictionary documentation should be read carefully so that you are at least
  1129. aware of all the various techniques available.  This is an important topic.
  1130.  
  1131.  
  1132. The word VARIABLE creates a 16-bit data 16-bit addressed variable, but you
  1133. can have 8-bit and 32-bit data variables and 32-bit addressed variables:
  1134.  
  1135. CVARIABLE    -> 8-bit data    16-bit addressed
  1136. VARIABLE     -> 16-bit data   16-bit addressed
  1137. DVARIABLE    -> 32-bit data   16-bit addressed
  1138.  
  1139. CVARIABLEL   -> 8-bit data    32-bit addressed
  1140. VARIABLEL    -> 16-bit data   32-bit addressed
  1141. DVARIABLEL   -> 32-bit data   32-bit addressed
  1142.          ^
  1143.      The "L" signifies 32-bit memory addressing.
  1144.  
  1145.  
  1146. Here is a VERY IMPORTANT thing to understand about HeliOS variables:
  1147.  
  1148. * A variable in HeliOS is merely a named function which returns the 16-bit
  1149.   or 32-bit address of the memory location where the first byte of the
  1150.   variable's data is stored.
  1151.  
  1152. For example:
  1153.  
  1154.         Memory cells
  1155.  
  1156.              |
  1157.              |            A HeliOS 8-bit data variable
  1158.              |            -----------------------------
  1159.              |
  1160.  One byte   >X<-------- HeliOS variable returns this address on the stack
  1161.  of storage  |
  1162.   (8-bit)    |
  1163.              |
  1164.  
  1165.  
  1166.              |
  1167.              |            A HeliOS 16-bit data variable
  1168.              |            -----------------------------
  1169.              |
  1170.  Two bytes  >X<-------- HeliOS variable returns this address on the stack
  1171.  of storage >X
  1172.  (16-bit)    |
  1173.              |
  1174.  
  1175.              |
  1176.              |            A HeliOS 32-bit data variable
  1177.              |            -----------------------------
  1178.              |
  1179.  Four bytes >X<-------- HeliOS variable returns this address on the stack
  1180.  of storage >X
  1181.  (32-bit)   >X
  1182.             >X
  1183.              |
  1184.  
  1185.  
  1186. Here is a another VERY IMPORTANT feature of HeliOS variables:
  1187.  
  1188. * All HeliOS variables are created and stored in the HeliOS Dictionary
  1189.   space, even if they are specified to return 32-bit addresses.
  1190.  
  1191.  
  1192. This leads on to another interesting fact about variables:
  1193.  
  1194. * All HeliOS variable addresses may be freely converted between 16-bit and
  1195.   32-bit addressing modes.
  1196.  
  1197.  
  1198. When a variable is created in HeliOS it always has to be initialised to a
  1199. value, but if no particular initial value is needed you can always set the
  1200. variable to zero to start with.
  1201.  
  1202. A variable created in this way allocates Dictionary memory space and stores
  1203. the new variable value along with header information.
  1204.  
  1205. For example,
  1206.  
  1207.     0 VARIABLE MILES
  1208.  
  1209. will create a VARIABLE called "MILES" initialised to zero.
  1210.  
  1211. In a similar manner,
  1212.  
  1213.     50 VARIABLE MILES
  1214.  
  1215. will create a VARIABLE called "MILES" and initialise it to 50.
  1216.  
  1217. Note that the above examples create a 16-bit data variable stored in the
  1218. 16-bit addressed HeliOS dictionary space.
  1219.  
  1220. We can now get and display the memory contents referenced by the word
  1221. "MILES" as follows:
  1222.  
  1223.     MILES @ .    "miles-fetch-print"
  1224.  
  1225. (or a shorter version:   "MILES ?"  which does exactly the same thing.)
  1226.  
  1227.  
  1228. What is actually happening here?
  1229.  
  1230.     MILES     \ Puts the address of the variable on the stack,
  1231.                     \ or, more accurately, the address of the memory
  1232.                     \ cell where the the value 50 is stored
  1233.  
  1234.     @    \ Gets the data stored at that memory address and
  1235.                     \ puts it on the stack, having first removed the
  1236.                     \ address from the stack
  1237.  
  1238.     .    \ Displays and removes the "top of stack" value
  1239.  
  1240. We have not specifically accessed memory numerically: we have just asked
  1241. for the contents of the VARIABLE defined by the name "MILES".
  1242.  
  1243. This use of easy to remember words (variable names) rather than numeric
  1244. values (memory addresses) is a great help in writing easily understood code.
  1245.  
  1246.  
  1247. Look how easy it is to store a value in a variable using "!" ("store"):
  1248.  
  1249.     12 MILES !    "twelve-miles-store"
  1250.  
  1251. This will store the value 12 in the memory location defined as "MILES".
  1252.  
  1253.  
  1254. Both 16-bit and 32-bit data storage variables can be created as follows:
  1255.  
  1256.  50 VARIABLE MILES
  1257.  
  1258.                Creates a 16-bit variable called 'MILES' and initialises
  1259.                it to 50.
  1260.  
  1261.                This variable is referenced by a 16-bit address.
  1262.  
  1263.                Use of the word 'MILES' puts a 16-bit address on the
  1264.                stack, specifying the memory location where the number
  1265.                50 is stored as a 16-bit number in the HeliOS dictionary
  1266.                memory space.
  1267.  
  1268.  
  1269.  50. DVARIABLE MILES
  1270.  
  1271.                Creates a 32-bit variable called 'MILES': the full stop
  1272.                after the "50" indicates that this is a 32-bit number.
  1273.  
  1274.                In this case the 32-bit data value is stored at a 16-bit
  1275.                address, and use of the word 'MILES' returns this 16-bit
  1276.                address where the 32-bit number "50." is stored.
  1277.  
  1278.                Note that the number 50 itself COULD be stored in an
  1279.                8-bit space: the data size refers to the storage space
  1280.                and not the size of the actual number stored there.
  1281.  
  1282.                The D prefix signifies a double length data variable:
  1283.                remember this, as it is the standard form of notation.
  1284.  
  1285.  
  1286.  50 VARIABLEL MILES
  1287.  
  1288.                Creates a 16-bit variable called 'MILES' stored in the
  1289.                Dictionary but referenced by a 32-bit or "Long" address.
  1290.  
  1291.                Use of the variable 'MILES' returns a 32-bit number on
  1292.                the stack representing the longword address where the
  1293.                16-bit value is stored.
  1294.  
  1295.                The L suffix signifies a long address: note again that this
  1296.                is a standard notation for "long" 32-bit addressing.
  1297.  
  1298.  
  1299.  50. DVARIABLEL MILES
  1300.  
  1301.                Creates a 16-bit variable called 'MILES' stored in the
  1302.                Dictionary but referenced by a 32-bit or "Long" address.
  1303.  
  1304.                Note the 32-bit data indicated by the "." after the "50"
  1305.                and the "D" prefix to indicate a 32-bit data variable.
  1306.  
  1307.                Note again the use of the "L" suffix to indicate the long
  1308.                addressing mode.
  1309.  
  1310.  
  1311. The above example illustrates the standard HeliOS data and addressing size
  1312. notation, which you should become familiar with as soon as possible.
  1313.  
  1314.  
  1315.  *  The D prefix always relates to double length 32-bit data.
  1316.  
  1317.  *  The L suffix relates to long 32-bit addresses.
  1318.  
  1319.  
  1320. At risk of being over repetitious, it is important to remember that ALL
  1321. variables are stored within the main HeliOS Dictionary, and can be 16-bit
  1322. addressed or 32-bit addressed.
  1323.  
  1324. Variables returning 16-bit addresses can have the 16-bit addresses converted
  1325. to 32-bit addresses by using the HeliOS Word "W>L" ("word-to-longword").
  1326.  
  1327. Variables returning 32-bit addresses can have the 32-bit addresses converted
  1328. to 16-bit addresses by using the HeliOS Word "L>W" ("longword-to-word").
  1329.  
  1330. Any address thus converted may be restored to its alternative form by using
  1331. the reverse operation.
  1332.  
  1333.  
  1334. ---------------------------------------
  1335. Using "Text Strings" in HeliOS programs
  1336. ---------------------------------------
  1337.  
  1338. The term "String" is used in relation to text storage in memory: since
  1339. computers only deal with numbers we have to represent text as a "string"
  1340. of numeric codes in memory.
  1341.  
  1342. Each text character is defined by a numeric code called an "ASCII" value,
  1343. one byte in size, which is a standard code used for representing letters
  1344. as numbers in the computer's memory.
  1345.  
  1346. A series of continuous bytes in memory which represent text ("ASCII")
  1347. characters make up a text "string".
  1348.  
  1349. To handle text strings we need to know where they start in memory, and also
  1350. where they stop (or how long they are).  This is accomplished by using two
  1351. different conventions which are each useful in different circumstances.
  1352.  
  1353. Strings are handled either as:
  1354.  
  1355.  1. "Counted Strings".
  1356.  
  1357.     These are always stored in a special format with a single "count" byte
  1358.     at the first position in the string.  This "count" byte specifies the
  1359.     length of the string in terms of its actual text character count, which
  1360.     can only be up to 255 characters in length.  These strings are commonly
  1361.     used in FORTH systems, and are generally quick and easy to handle, but
  1362.     they are not used by the Amiga operating system and library functions.
  1363.  
  1364.  2. "Null-terminated Strings"
  1365.  
  1366.     These strings include no size information, and simply start at the
  1367.     string address with the first text character.  The length of the string
  1368.     is determined by specifying its end point, which is defined by placing
  1369.     a "null" or "0" character after the last text character.  These strings
  1370.     can be any length, and are generally used as the standard string format
  1371.     by Amiga operating system functions and library calls.
  1372.  
  1373. Important note:
  1374.  
  1375. * In HeliOS all counted strings also have a terminating "null", allowing
  1376.   them to be used as uncounted strings by using the first actual text
  1377.   character as the string start after skipping past the "count" byte.
  1378.  
  1379. In both types of string a memory address is used to specify the start of the
  1380. string, and this address value is used as a "handle" when manipulating the
  1381. string.
  1382.  
  1383. As with numeric data a string "address pointer" can be used as a simple
  1384. number on the stack, or may be "named" like a variable.
  1385.  
  1386. HeliOS has functions for creating and handling string variables, and these
  1387. are similar and equivalent to the functions for numeric variables.
  1388.  
  1389. Remember these points:
  1390.  
  1391. * The first byte of a counted string is always called the "count byte" and
  1392.   holds a single-byte number specifying the total number of text characters
  1393.   in the string.
  1394.  
  1395. * Counted strings have limited length, since the single "count" byte has a
  1396.   maximum value of 255.
  1397.  
  1398. * In the case of the "null terminated" string the first byte of the string
  1399.   is simply the first character of the string itself, which continues on in
  1400.   memory until a null value "0" occurs: hence its name.
  1401.  
  1402. * Null terminated strings can be of any length.
  1403.  
  1404. * Traditionally Forth used counted strings, but the Amiga operating system
  1405.   uses null terminated strings.
  1406.  
  1407. * HeliOS has comprehensive support for both counted and uncounted strings,
  1408.   including easy functions for conversion from one type to the other.
  1409.  
  1410. * HeliOS has the extra useful feature that all counted strings all have a
  1411.   terminating null also.  To access a counted string as "null terminated"
  1412.   all you have to do is increment the address of the string by one, thus
  1413.   moving forward past the initial "count" byte to the first character.
  1414.  
  1415. HeliOS has a large number of string handling routines, many of which handle
  1416. either 16-bit or 32-bit addressed strings.
  1417.  
  1418. As a general rule, you can handle all strings as 16-bit addressed in simple
  1419. programs where you are using the Dictionary memory for string storage.
  1420.  
  1421. It is also usually a good idea to use counted strings where possible, since
  1422. these are generally easier to use and have more powerful string manipulation
  1423. functions.
  1424.  
  1425. However, if you need to pass any string to an Amiga library function you
  1426. will need to convert the string to 32-bit addressed using "W>L", and you
  1427. will also need to make sure that you specify the string in uncounted form.
  1428.  
  1429. Remember that you can simply add 1 to the string address pointer to convert
  1430. a counted string to an uncounteed string for an Amiga library call.
  1431.  
  1432. Note here that in this case the string itself is still left unchanged, and
  1433. remains stored as a counted string in memory: it is merely the POINTER to
  1434. the string which you change when passing it to the Amiga library call.
  1435.  
  1436.  
  1437. --------------------------------------------------------------
  1438. A very simple and useful HeliOS string handling word - "LIT$".
  1439. --------------------------------------------------------------
  1440.  
  1441. The word LIT$ can only be used within colon definitions.
  1442.  
  1443. LIT$ is used within a colon definition to allow compilation of a counted
  1444. string within your program code.  The text string itself must be enclosed
  1445. between two dollar ("$") characters, as this example shows:
  1446.  
  1447.   : PRESSMESSAGE   LIT$ $Press SPACE-BAR To Continue$ ;
  1448.                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  1449.                                 Text string
  1450.  
  1451. This example creates a new word PRESSMESSAGE, which employs "LIT$" to store
  1452. the text between the two dollar characters ("Press SPACE-BAR To continue")
  1453. within the dictionary.
  1454.  
  1455. When you later use the word PRESSMESSAGE the 16-bit address of the counted
  1456. string will be returned on the stack.
  1457.  
  1458. It can then, for example, be printed out to the screen using the word "$."
  1459. in another word as follows:
  1460.  
  1461.   : SHOWPRESMESSAGE   PRESSMESSAGE $. ;
  1462.  
  1463. You will find this little word "LIT$" VERY useful indeed: we use it in the
  1464. example program below, and you should learn to use it yourself in your own
  1465. programs as soon as possible.
  1466.  
  1467. There is also a 32-bit version of LIT$ called LIT$L, which returns a 32-bit
  1468. string address on the stack at run time, instead of a 16-bit string address.
  1469.  
  1470.  
  1471. -------------------------------------
  1472. General INPUT and OUTPUT using HeliOS
  1473. -------------------------------------
  1474.  
  1475. Obtaining User Input:
  1476.  
  1477. HeliOS has a general purpose user input interrogation word, called "KEY".
  1478.  
  1479. This word "KEY" causes a program to wait for user input, then it returns a
  1480. code on the HEliOS stack defining exactly what type of input event occurred.
  1481.  
  1482. Input events include keyboard entries, menu selections, mouse button clicks,
  1483. mouse movement, gadget selection, menu selection, ticker activation etc..
  1484.  
  1485. HeliOS uses the word "KEY" because traditional Forth used this word, but
  1486. in Forth this word only accessed keyboard events, unlike the much extended
  1487. HeliOS version which handles ALL Intuition graphical user interface events.
  1488.  
  1489. The user input word "KEY" will report input events from whatever active
  1490. Intuition window you specify.
  1491.  
  1492. You must tell HeliOS which window to check for user input by specifying a
  1493. current input window using the HeliOS word "MAKEINWINDOW".
  1494.  
  1495. MAKEINWINDOW is an immensely powerful and important word, as it actually
  1496. runs a separate Amiga task dedicated to handling user input in designated
  1497. Intuition widows.
  1498.  
  1499. The MAKEINWINDOW command sets up a very extensive program to handle all
  1500. types of user input, which in any other Amiga language you would have to
  1501. write for yourself.
  1502.  
  1503. This event reporting program running from its own Amiga task translates all
  1504. input events into whatever form the main HeliOS program requires, and has
  1505. many very sophisticated features unique to HeliOS.
  1506.  
  1507. All this power translates, from your point of view, to the easy use of the
  1508. single word "KEY": all the hard work is done for you, and most of the time
  1509. you never need be concerned with the underlying mechanism.
  1510.  
  1511. You can learn more about these functions in the "Dictionary.doc" and in
  1512. the later tutorials.
  1513.  
  1514.  
  1515. ------------------------------------------------------
  1516. Sending text output to the user via the screen display
  1517. ------------------------------------------------------
  1518.  
  1519. There are two basic types of screen text output:
  1520.  
  1521. 1. Console text output
  1522.  
  1523.    This is a method of outputting text to a special text handling program
  1524.    called a "console" which allows various auto-formatting facilities etc.
  1525.  
  1526.    Text characters are, in HeliOS, usually written to console windows using
  1527.    a system of streams, which have full scrolling, cursor movement, and text
  1528.    formatting facilities etc.
  1529.  
  1530.    In general all dynamic, changing text output is handled by "console" type
  1531.    displays.
  1532.  
  1533. 2. Graphic text output
  1534.  
  1535.    This is a method of outputting text in simple graphical form, as a
  1536.    series of letters represented by graphical symbols, without any form
  1537.    of control or formatting.
  1538.  
  1539.    Graphic text output does not have any "text control" features and all
  1540.    text is placed on the screen as a static graphic "drawing".  This means
  1541.    that, for example, text can only be deleted by overwriting the screen
  1542.    area occupied by the graphic image of the text.
  1543.  
  1544.    In general graphic text output is used for "painting" a graphic display
  1545.    with static text.
  1546.  
  1547. Both kinds of text are fully supported by HeliOS, but the following
  1548. simple examples use "console" text output for simplicity.
  1549.  
  1550. Note that this console output is not always simple on the Amiga, and in
  1551. other languages quite a lot of programming is required to set up console
  1552. output.
  1553.  
  1554. HeliOS is unique in the power of its automated text console functions, and,
  1555. as you will see, console text output has been made very easy indeed.
  1556.  
  1557. As a matter of interest, HeliOS has two powerful sub-programs which fully
  1558. automate the setting up of:
  1559.  
  1560. 1. Sophisticated console text output
  1561.  
  1562. 2. Comprehensive Amiga graphic library graphical operations
  1563.  
  1564. within ANY designated window on ANY screen.
  1565.  
  1566. Quite large programs would have to be written by you in any other language
  1567. to achieve this functionality of HeliOS, which requires you to use just one
  1568. word to set up each sub-program.
  1569.  
  1570. Here are the two important HeliOS output configuration functions:
  1571.  
  1572. 1. MAKOUTWINDOW   - Sets up a very sophisticated console handling system
  1573.                     with 10 automated text "streams".
  1574.  
  1575.                     This word is used to attach a text output console to a
  1576.                     window and make this the current text output window.
  1577.  
  1578.                     This works with any Intuition window.
  1579.  
  1580. 2. MAKEGFXWINDOW  - Sets up an automated graphics library handling system
  1581.                     with single word operators for most graphic functions.
  1582.  
  1583.                     This word is used to set up all HeliOS graphic output
  1584.                     commands for a window and make this the current graphic
  1585.                     output window.
  1586.  
  1587.                     This works with any Intuition window.
  1588.  
  1589. Our final example program below will show you how to use these functions,
  1590. and later tutorials will explain more about them.
  1591.  
  1592.  
  1593. --------------------------------------
  1594. A simple tutorial programming exercise
  1595. --------------------------------------
  1596.  
  1597. Now let us look at a simple programming exercise.
  1598.  
  1599. Our next short tutorial program will start with a line of code which clears
  1600. all words from the user dictionary, leaving just the CORE vocabulary.
  1601.  
  1602. This is a useful way to start any HeliOS program, since it ensures that the
  1603. system is clear each time you compile the program.
  1604.  
  1605.  
  1606.   FORGET **CORE**          \ Get rid of any old USER defined words
  1607.  
  1608.  
  1609. The "\" character denotes an "end of line comment", and anything following
  1610. this is ignored by the compiler.  Always add plenty of descriptive comments
  1611. to your code in this way, so that you know what is going on.
  1612.  
  1613. Remember here that ALL words in HeliOS source code need a space before and
  1614. after them.  This is absolutely vital, and note that a space is also needed
  1615. both before and after the "\" character, because this is also a HeliOS Word.
  1616.  
  1617. To summarise these points, the above line of code has:
  1618.  
  1619.     At least one space
  1620.  
  1621.     The word "FORGET"
  1622.  
  1623.     At least one space
  1624.  
  1625.     The word "**CORE**" telling FORGET to clear all words back to CORE
  1626.  
  1627.     At least one space
  1628.  
  1629.     The word "\" which tells us that the rest of the line is a comment
  1630.  
  1631.     At least one space
  1632.  
  1633.     The words "Get rid of any old USER defined words" (the comment)
  1634.  
  1635.  
  1636. Now we will add a "colon definition" to our program.
  1637.  
  1638.  
  1639.   FORGET **CORE**                \ Get rid of any old USER defined words
  1640.  
  1641.   : SAYHELLO ." HELLO WORLD" ;   \ Make a word called SAYHELLO
  1642.  
  1643.  
  1644. The colon definition above will create a new subroutine called SAYHELLO.
  1645.  
  1646. Let us look at it's structure. It has:
  1647.  
  1648.     At least one space
  1649.  
  1650.     A ":" to start the definition
  1651.  
  1652.     At least one space
  1653.  
  1654.     A descriptive function name ->  "SAYHELLO"
  1655.  
  1656.     At least one space
  1657.  
  1658.     The definition ->  ." HELLO WORLD"
  1659.  
  1660.     At least one space
  1661.  
  1662.     A ";" to finish the definition
  1663.  
  1664.     At least one space
  1665.  
  1666.     A "\" which tells us that the rest of the line is a comment
  1667.  
  1668.     At least one space
  1669.  
  1670.     The words "Make a word called SAYHELLO" (the comment)
  1671.  
  1672.  
  1673. We now have a complete small program:
  1674.  
  1675.  
  1676.   FORGET **CORE**               \ Dispose of any old USER defined words
  1677.  
  1678.   : SAYHELLO ." HELLO WORLD" ;  \ Make a subroutine called SAYHELLO
  1679.  
  1680.  
  1681. Let us examine the definition of SAYHELLO, which is:
  1682.  
  1683.  ." HELLO WORLD"
  1684.  
  1685.  
  1686. This can be analysed into three parts as follows.
  1687.  
  1688. <SPACE>   ."   <SPACE>   HELLO WORLD      "
  1689.           ^^             ^^^^^^^^^^^      ^
  1690.        Function             Text      Delimiter
  1691.  
  1692.  
  1693. The first part is the HeliOS word ." which tells the HeliOS system to output
  1694. to the screen the words following it up to the next " character.
  1695.  
  1696. The second part is the expression HELLO WORLD, which is the message we want
  1697. to display.
  1698.  
  1699. The third part is the quote character " which tells the HeliOS system that
  1700. our enclosed quotation has ended.
  1701.  
  1702. The double quote " is not a HeliOS WORD and does not need a space before it:
  1703. it is called a delimiter and merely acts to delimit the end of an enclosed
  1704. text message "string".
  1705.  
  1706. To use the new word (or subroutine) all we need to do is either type its
  1707. name at the command line after compiling our program, or include its name
  1708. in our program code.
  1709.  
  1710.  
  1711. --------------------------------------
  1712. Entering and compiling our new program
  1713. --------------------------------------
  1714.  
  1715. There are two main ways of entering code.
  1716.  
  1717. We can either use an editor, or we can type in code at the the command line.
  1718.  
  1719. The editor option is perhaps better in most cases because code can be saved
  1720. to, and loaded from, disk files.
  1721.  
  1722. However, the command line is very quick and convenient, and has a circular
  1723. "history" buffer, making it useful for testing small fragments of code which
  1724. are being continually modified.
  1725.  
  1726. The command line "history" buffer allows you to use the up/down cursor keys
  1727. to bring back any previously typed command lines and reuse them.
  1728.  
  1729. In general the command line is very useful for small code testing jobs, but
  1730. cannot be saved to disk and is clumsy for entering larger code sections.
  1731.  
  1732. We will use an editor in this tutorial example, as follows:
  1733.  
  1734. 1.  Click one of the "Ed x" buttons at the top of the screen to enter an
  1735.     empty editor (use the "Clear text" menu option if necessary).
  1736.  
  1737. 2.  Now type in the following code:
  1738.  
  1739.     FORGET **CORE**              \ Dispose of any USER defined words
  1740.  
  1741.     : SAYHELLO ." HELLO WORLD" ; \ Make a word called SAYHELLO
  1742.  
  1743.     SAYHELLO                     \ Use the new word we have created
  1744.  
  1745.     WAITSPACE                    \ Wait for the space bar to be pressed
  1746.  
  1747. 3.  Then compile the code in the editor (you can use <Ctrl-5>).
  1748.  
  1749.  
  1750. This action will take you into the Interpreter and run the program.
  1751.  
  1752. Typing in the text is a worthwhile exercise, since it helps familiarise
  1753. you with the process of entering source code.
  1754.  
  1755. However, you can always use the cut and paste functions if you like, or
  1756. even, if you wish, you can simply run the code directly by using <Amiga-e>
  1757. after highlighting the text in this editor.
  1758.  
  1759.  
  1760. Our little program above actually does something: it will print to the
  1761. screen the message "HELLO WORLD".
  1762.  
  1763. Note that you can now type SAYHELLO at the command line and the message
  1764. "HELLO WORLD" will appear on screen.
  1765.  
  1766.  
  1767. The next thing to do is save your new program source code to a disk file:
  1768.  
  1769. 1. Re-enter the editor containing your code.
  1770.  
  1771. 2. Select "Save As" from the "Load/Save" menu to access the HeliOS File
  1772.    Requester.
  1773.  
  1774. 3. Save the file with a name and path of your choice.
  1775.  
  1776.    Note that each time you resave a file with the same name as before
  1777.    HeliOS will create a backup file for you automatically.
  1778.  
  1779. Having created and saved a small working program, we can now start to do
  1780. some more interesting things with it.
  1781.  
  1782. Listed below are a number of variations on our program for you to try.
  1783.  
  1784. Some of the examples below use HeliOS functions which you may not yet be
  1785. familiar with: nevertheless they are quite easy to follow, and you should
  1786. be able to make sense of what is happening.
  1787.  
  1788. Things such as DO...LOOP constructs and the use of Return stack functions
  1789. will be explained in later tutorials, but for now you should look at the
  1790. examples given and try to get the general idea of how things work.
  1791.  
  1792. Use the editor again to modify the code you have already entered, then use 
  1793. the methods outlined above to save and execute your code.
  1794.  
  1795. Note that you can omit the comments if you like.
  1796.  
  1797. Try each of the following variations:
  1798.  
  1799.  
  1800.   : SAYHELLO             \ This version changes the output text position
  1801.  
  1802.   10 10 CURPUT           \ Set the text output position ("PUT" the "CURSOR")
  1803.  
  1804.   ." HELLO WORLD"        \ Say hello
  1805.   ;
  1806.  
  1807.  
  1808.   : SAYHELLO             \ This changes the output text position and colour
  1809.  
  1810.   6 FPENSET              \ Set the foreground pen - text colour
  1811.   7 BPENSET              \ Set the background pen - text background
  1812.   10 10 CURPUT           \ Set the text output position ("PUT" the "CURSOR")
  1813.  
  1814.   ." HELLO WORLD"        \ Say hello
  1815.   ;
  1816.  
  1817.  
  1818.   : SAYHELLO             \ This displays the message 4 times in line
  1819.  
  1820.   4 0
  1821.   DO                     \ Loop 4 times
  1822.     ." HELLO WORLD"      \ Say hello
  1823.     SPACE                \ Put a space between messages
  1824.   LOOP
  1825.   ;
  1826.  
  1827.  
  1828.   : SAYHELLO             \ To display the message 4 times on new lines
  1829.  
  1830.   4 0
  1831.   DO                     \ Loop 4 times
  1832.     CR                   \ "Carriage Return" =  Go to start of next line
  1833.     ." HELLO WORLD"      \ Say hello
  1834.   LOOP
  1835.   ;
  1836.  
  1837.  
  1838.   Now for a more elaborate one........
  1839.  
  1840.  
  1841.   : SAYHELLO             \ This repeats the message 4 times on new lines
  1842.                          \ in a box
  1843.  
  1844.   SCRCLR
  1845.  
  1846.   6 FPENSET              \ Set the foreground pen - text colour
  1847.   7 BPENSET              \ Set the background pen - text background
  1848.  
  1849.   7 GFXSETAPEN           \ Set the graphics drawing colour (box colour)
  1850.   1 GFXSETOPEN           \ Set the graphics outline pen colour (box outline)
  1851.  
  1852.   1 GFXOUTLINE           \ Switch on graphics OUTLINE mode
  1853.  
  1854.   10                     \ Pixel "x" pos of the box's top left hand corner,
  1855.                          \ measured from top left hand corner of screen
  1856.   45                     \ Top left "y" pos
  1857.   150                    \ Bottom right "x" pos
  1858.   90                     \ Bottom right "y" pos
  1859.   GFXRECTFILL            \ Draw a filled rectangle (draw box)
  1860.  
  1861.   0 GFXOUTLINE           \ Switch off graphics OUTLINE mode
  1862.  
  1863.   4 0
  1864.   DO                     \ Loop 4 times
  1865.     CR                   \ "Carriage Return" =  Go to start of next line
  1866.     4 CURFW              \ Move the "CURSOR FORWARD" to give a margin
  1867.     ." HELLO WORLD"      \ Say Hello
  1868.   LOOP
  1869.   WAITSPACE
  1870.   ;
  1871.  
  1872.  
  1873.   And now an even more elaborate one........
  1874.  
  1875.  
  1876.   : SAYHELLO             \ This repeats the message 4 times on new lines
  1877.                          \ in a box
  1878.  
  1879.   SCRCLR
  1880.  
  1881.   6 FPENSET              \ Set the foreground pen - text colour
  1882.   7 BPENSET              \ Set the background pen - text background
  1883.  
  1884.   7 GFXSETAPEN           \ Set the graphic drawing colour (box colour)
  1885.   1 GFXSETOPEN           \ Set the graphics outline pen colour (box outline)
  1886.   1 GFXOUTLINE           \ Switch on graphics OUTLINE mode
  1887.  
  1888.   10                     \ Pixel "x" pos of the box's top left hand corner,
  1889.                          \ measured from top left hand corner of screen
  1890.   45                     \ Top left "y" pos
  1891.   150                    \ Bottom right "x" pos
  1892.   90                     \ Bottom right "y" pos
  1893.   GFXRECTFILL            \ Draw a filled rectangle (draw box)
  1894.  
  1895.   0 GFXOUTLINE           \ Switch off graphics OUTLINE mode
  1896.  
  1897.   4 0
  1898.   DO                     \ Loop 4 times
  1899.     4                    \ Start at 4th position on line
  1900.     I 2 +                \ Start at 2nd line + LOOP INDEX
  1901.     CURPUT               \ PUT the CURSOR
  1902.     ." This is line "    \ Print "This is line"
  1903.     I 1+                 \ Increment the LOOP INDEX + 1 which is stored
  1904.                          \ on the stack, (the index starts at 0)
  1905.     .                    \ Print the index number (stored on the stack)
  1906.   LOOP
  1907.  
  1908.   WAITSPACE
  1909.   ;
  1910.  
  1911. Look at these various examples and try changing things until you are quite
  1912. familiar with the general process of editing, saving and compiling.
  1913.  
  1914. **************************************************************************
  1915.  
  1916. ----------------------------------------
  1917. Using Amiga Libraries from within HeliOS
  1918. ----------------------------------------
  1919.  
  1920. Amiga Libraries are special code modules which are provided to help you
  1921. with various programming tasks, and are very simple to use.
  1922.  
  1923. Libraries are either present within the Amiga ROM (Read Only Memory), or
  1924. may be automatically loaded from disk.
  1925.  
  1926. The overall method of accessing a library is:
  1927.  
  1928.  1.  OPEN the library       The Amiga loads and prepares it for use
  1929.  
  1930.  2.  CALL library routines  You will need a reference book for definitions
  1931.  
  1932.  3.  CLOSE the library      When you have finished with it
  1933.  
  1934.  
  1935. Functions accessing many of the more frequently required Amiga ROM library
  1936. routines are included in HeliOS as part of the CORE dictionary.
  1937.  
  1938. These functions are effectively pre-written "interfaces" to specific Amiga
  1939. library calls and do not require you to address the library directly.
  1940.  
  1941. In addition, the main and most useful libraries are automatically opened for
  1942. you when HeliOS starts up and closed when HeliOS closes down.
  1943.  
  1944. These are the DOS, EXEC, GRAPHICS, LAYERS, and INTUITION libraries.
  1945.  
  1946. If you do have to open a library yourself there is a simple to use HeliOS
  1947. word called OPENLIB, which opens a library and returns the 32-bit library
  1948. base address on the stack.
  1949.  
  1950. Once you have opened a library you must always store the 32-bit library base
  1951. address in a standard HeliOS DVARIABLE for use later by the HeliOS library
  1952. calling function.
  1953.  
  1954. When you have finished with the library you should always use the HeliOS
  1955. CLOSELIB function to close it down.
  1956.  
  1957. As an example we will show how to open "diskfont.library".
  1958.  
  1959. First we need to initialise a DVARIABLE to store the library base address 
  1960. when we have opened the library.
  1961.  
  1962.  0. DVARIABLE DFONTBASE  \ Create a 32-bit variable DFONTBASE
  1963.  
  1964.  
  1965. Now we open the library and store the library base address.........
  1966.  
  1967.  LIT$ $diskfont.library$    \ Put counted library name string on stack
  1968.  0                          \ Put library revision number on stack
  1969.  OPENLIB                    \ OPEN the library
  1970.  DFONTBASE D!               \ Store the library handle
  1971.  
  1972.  
  1973. Having attempted to open a library, you should always check to see that the
  1974. returned library base is not zero, in which case the library has failed to
  1975. open for some reason and you need to sort out the problem.
  1976.  
  1977. Something like this:
  1978.  
  1979. DFONTBASE D@ D0<> 
  1980. IF 
  1981. ..........etc.
  1982.  
  1983. -----------------
  1984. Closing a library
  1985. -----------------
  1986.  
  1987. To close a library all you have to do is put the library base address on
  1988. the stack and use the word CLOSELIB, like this:
  1989.  
  1990.   DFONTBASE D@ CLOSELIB
  1991.  
  1992. That's all there is to it!
  1993.  
  1994. Important notes:
  1995.  
  1996. * Remember that you only need to close the libraries which you yourself
  1997.   have specifically opened.
  1998.  
  1999. * You do not need to close (and MUST not close) the standard libraries
  2000.   handled for you by HeliOS system.
  2001.  
  2002. ---------------------
  2003. Making a library call
  2004. ---------------------
  2005.  
  2006. When a library is open, and you want to use it, you need to know how to
  2007. specify parameters and call individual library routines.
  2008.  
  2009. HeliOS has a very simple library calling mechanism which is very similar to
  2010. the methods used for assembly language.
  2011.  
  2012. When you are looking up library functions in general Amiga documentation
  2013. you should always consult the information referring to assembly language
  2014. library calls: this information can be used directly in HeliOS.
  2015.  
  2016. If you look at the Amiga library documentation you will see that there are
  2017. instructions for assembly language library calls, telling the programmer in
  2018. which MC680xx microprocessor registers to store parameters.
  2019.  
  2020. You can gather from this that in assembly language you store parameters
  2021. directly into the registers within the MC680xx microprocessor before calling
  2022. a library.
  2023.  
  2024. The results of library calls are also stored in these MC680xx registers when
  2025. the library call has been completed.
  2026.  
  2027. Don't worry if this sounds difficult - it is actually very easy!
  2028.  
  2029. The MC680xx has a set of 8 ADDRESS registers, labelled A0-A7, and a set of
  2030. 8 DATA registers, labelled D0-D7: these registers are all 32-bit registers.
  2031.  
  2032. Your library documentation will tell you to:
  2033.  
  2034. Put a certain parameter value into register A0
  2035. Put a certain parameter value into register D0
  2036. etc.
  2037. etc.
  2038.  
  2039. Call a Library function at a certain specified offset from the library base
  2040.  
  2041. Read result of call from register D0
  2042. etc.
  2043. etc.
  2044.  
  2045.  
  2046. Here, then, is what you need to know before calling a library function:
  2047.  
  2048. 1.      What is the library base offset for the routine you wish to call?
  2049.  
  2050.         This is found from Amiga documentation and will always be a negative
  2051.         number.
  2052.  
  2053.         You can use an include symbolic value if you wish.
  2054.  
  2055. 2.      What "parameters" does that library call require before using it?
  2056.  
  2057.         These details are found in Amiga library documentation, and you
  2058.         need to look for MC680xx register useage, as with assembly language
  2059.         library calls.
  2060.  
  2061. 3.      What results are returned after completion?
  2062.  
  2063.         These details are found in Amiga library documentation, and you
  2064.         need to look for MC680xx register useage, as with assembly language
  2065.         library calls.
  2066.  
  2067.  
  2068. So, how do we use this information to make a library call in HeliOS?
  2069.  
  2070. As we said, HeliOS is very close to assembly language in operation, so it
  2071. handles library calls in a manner closely reflecting the way it is done in
  2072. assembly language, by storing parameters in MC680xx registers.
  2073.  
  2074. But, you might ask, how can we use MC680xx registers from within HeliOS?
  2075.  
  2076. Well, to translate this type of operation into HeliOS is very easy because
  2077. you have a set of DUMMY MC680xx registers in which to store your parameters
  2078. and read your results.
  2079.  
  2080. The DUMMY ADDRESS REGISTERS are accessed as double number (32-bit) variables
  2081. by putting the register number you require on the HeliOS stack and then
  2082. using the word AREG to return the variable address.
  2083.  
  2084. For example:
  2085.  
  2086. 0 AREG -> Returns 16-bit address of 32-bit data store for DUMMY A0 register
  2087. 1 AREG -> Returns 16-bit address of 32-bit data store for DUMMY A1 register
  2088.  
  2089. etc.
  2090.  
  2091. The same method applies to DUMMY DATA REGISTERS but this time you use the
  2092. word DREG.
  2093.  
  2094. For example:
  2095.  
  2096. 0 DREG -> Returns 16-bit address of 32-bit data store for DUMMY D0 register
  2097.  
  2098. When HeliOS calls a library for you, using the HeliOS Word LIBRARY, it
  2099. simply unloads the dummy registers into the actual MC680xx processor
  2100. registers, calls the library, then unloads the MC680xx registers back
  2101. into the dummy registers.
  2102.  
  2103. Notice that this technique is doubly useful, because it means that all the
  2104. values in the dummy registers are automaticaly stored and retained for your
  2105. use until the next time you prepare a library call or reset the registers.
  2106.  
  2107.  
  2108. To carry out the example library call given above you would:
  2109.  
  2110. Put a certain parameter value into HeliOS DUMMY MC680xx register A0
  2111. Put a certain parameter value into HeliOS DUMMY MC680xx register D0
  2112. etc.
  2113. etc.
  2114.  
  2115. Call HeliOS LIBRARY function with specified offset
  2116.  
  2117. Read result of call from HeliOS DUMMY MC680xx register D0
  2118. etc.
  2119. etc.
  2120.  
  2121.  
  2122. To do this in actual Helios code you might write something like this:
  2123.  
  2124.  PARAMETER1 D@      \ Get parameter onto stack
  2125.  0 AREG D!          \ Store it in DUMMY ADDRESS REGISTER A0
  2126.  
  2127.  PARAMETER2 D@      \ Get parameter onto stack
  2128.  0 DREG D!          \ Store it in DUMMY DATA REGISTER D0
  2129.  
  2130.  LIBRARYBASE        \ Put address of Library base store onto stack
  2131.  -64                \ Get library offset onto stack
  2132.  LIBRARY            \ Call library
  2133.  
  2134.  0 DREG D@          \ Get result from DUMMY DATA REGISTER D0 onto stack
  2135.  
  2136. Remember, the dummy registers will always directly reflect their MC680xx
  2137. counterparts before and after the library call.
  2138.  
  2139. The word LIBRARY which makes the call is not at all complicated, you simply
  2140. put the name of the variable where the library base address is stored onto
  2141. the stack, followed by the library routine offset, then use the word
  2142. LIBRARY exactly as shown above.
  2143.  
  2144. Note that it is not the library base pointer itself that is used by the
  2145. word "LIBRARY" but a 16-bit HeliOS storage variable address (the reason
  2146. for this is that this arrangement gives slightly faster performance).
  2147.  
  2148. That is all there is to calling Amiga libraries, except for one last thing
  2149. which makes your task even easier.
  2150.  
  2151. In the above code we have accessed the result of the library call in dummy
  2152. register D0 quite correctly by using the code sequence "0 DREG D@".
  2153.  
  2154. However, because this code sequence is used very often, HeliOS includes an
  2155. easy single word alternative "D0RESULT".
  2156.  
  2157. * Instead of typing "0 DREG D@" you can simply type the one word "D0RESULT"
  2158.   to get the value in DUMMY REGISTER D0.
  2159.  
  2160.  
  2161. --------------------------------------------------
  2162. Making a call to external assembler-generated code
  2163. --------------------------------------------------
  2164.  
  2165. You may wish at some point to include assembly language sections within
  2166. your HeliOS programs.
  2167.  
  2168. You can do this in three ways:
  2169.  
  2170. 1. Using the HeliOS integrated assembler.
  2171.  
  2172.    This is OK for simple sections of in-line assembler code, but is more
  2173.    clumsy to use than a fully featured separate dedicated assembler.
  2174.  
  2175. 2. Creating an Amiga library by writing code in an assembler and then using
  2176.    a utility such as the PD program "LibTool" to generate an Amiga library
  2177.    from your code.
  2178.  
  2179.    This new library can then be called like any other library from HeliOS.
  2180.  
  2181. 3. Creating an executable program in an assembler and then executing it
  2182.    from within HeliOS.
  2183.  
  2184. This third method is a very efficient and easy way of accessing assembler
  2185. code from within HeliOS, and we will now discuss it in more detail.
  2186.  
  2187. Firstly you need to generate an assembly language program with all the
  2188. components which you want to access from HeliOS defined in an initial
  2189. table, like this:
  2190.  
  2191. dc.l MyRoutine1
  2192. dc.l MyRoutine2
  2193. dc.l MyRoutine3
  2194. dc.l MyRoutine4
  2195.  
  2196. MyRoutine1 move.w etc. etc.
  2197.            move.w etc. etc.
  2198.            rts
  2199.  
  2200. MyRoutine2 move.w etc. etc.
  2201.            move.w etc. etc.
  2202.            rts
  2203.  
  2204. etc. etc.
  2205.  
  2206. Remember to create the initial longword reference table at the start of
  2207. the assembler program code because you will need to use this from within
  2208. HeliOS to access the individual parts of your program.
  2209.  
  2210. Assemble the program into an executable file, and then you can load it
  2211. into memory from within HeliOS using the DOS LoadSeg/UnLoadSeg routines,
  2212. which allow you to load an external program into memory.
  2213.  
  2214. Here is a short example of how you might do this:
  2215.  
  2216. \ First set up some storage facilities......
  2217.  
  2218. 0. DVARIABLE Load_SegList      \ Loaded SegList BPTR
  2219. 0. DPOINTER  Load_CodePtr      \ Pointer to loaded code
  2220.  
  2221. \ Load your code......
  2222.  
  2223. : Code_LoadSeg
  2224.  
  2225.   LIT$ $Code.exe$ W>L D1+        \ Uncounted filename
  2226.  
  2227.   1 DREG D!                      \  -> Reg D1
  2228.  
  2229.   _LVOLoadSeg DOSBASE LIBRARYL   \ Call DOS "LoadSeg"
  2230.  
  2231.   D0RESULT D0= ERROR" Error!"    \ Error check
  2232.  
  2233.   D0RESULT
  2234.   DDUP Load_SegList D!           \ Store SegList
  2235.   2 DLSL                         \ Convert BPTR to APTR
  2236.   4. D+                          \ Get code start offset
  2237.   Load_CodePtr MAKEPOINTER       \ Set up pointer
  2238.   ;
  2239.  
  2240. \ Don't forget a routine to unload your code when you are done......
  2241.  
  2242.   : Code_UnLoadSeg
  2243.  
  2244.   Load_SegList D@ 1 DREG D!      \ SegList -> Reg D1                                               ; SegList -> Reg D1
  2245.   _LVOUnLoadSeg DOSBASE LIBRARYL \ Call DOS "UnLoadSeg"
  2246.   ;
  2247.  
  2248. Having loaded your code into memory using "Code_LoadSeg", it is very easy
  2249. to call any routine with the code from your HeliOS program.
  2250.  
  2251. To do this you would use the HeliOS "JSR" function.
  2252.  
  2253. Assuming that your routines withing the external assembler code are listed
  2254. in order at the start of the code, you can access any of them like this:
  2255.  
  2256.   : Code_RunExt                  \ ( Routine number (w) - - - )
  2257.  
  2258.   4 m* Load_CodePtr D+ D@L       \ Get routine pointer from initial table
  2259.   JSR                            \ JSR to loaded code routine
  2260.   ;
  2261.  
  2262. The "JSR" function will automatically handle the interfacing of HeliOS
  2263. to the assembler code, and parameters are passed using the HeliOS dummy
  2264. MC680xx registers, exactly as with HeliOS library calls.
  2265.  
  2266. This means that whatever values you set into the dummy registers (using
  2267. AREG and DREG) will be stored in the actual MC680xx registers before the
  2268. JSR function enters the machine code routine.
  2269.  
  2270. Of course the dummy registers also return with the actual MC680xx register
  2271. values when your assembpler code does a final "RTS".
  2272.  
  2273. As you can see, this is a very simple (and powerful) method of accessing
  2274. external assembler code.
  2275.  
  2276.  
  2277. ----------------------------------------------------
  2278. General procedures for Starting and Closing programs
  2279. ----------------------------------------------------
  2280.  
  2281. It is a good idea to stick to a regular procedure (hopefully a good one)
  2282. when writing all your programs.  Especially in code which starts and closes
  2283. down your programs, it is possible and desirable to use a standard set of
  2284. prewritten subroutines which can be modified as required.
  2285.  
  2286. There are several rules that you should follow to produce good, safe code.
  2287.  
  2288. 1. Always try to mirror opening and closing calls.
  2289. 2. Always try to have ONE universal and thorough exit point.
  2290. 3. Always make sure you close down everything you open, especially memory.
  2291. 4. Always make sure to initialise variables correctly in RUN-TIME code.
  2292. 5. Always check the memory available before and after using a program: if
  2293.    you are losing memory something is very wrong.
  2294. 6. Always arrange your own output screen/window for serious programs. You
  2295.    can't use the interactive HeliOS window in stand-alone compiled code,
  2296.    for the simple reason that it won't be there!
  2297.  
  2298.  
  2299. It is a good idea to use standard start-up and close-down words for all
  2300. your programs.
  2301.  
  2302. Any special functions needed for particular programs may be handled as
  2303. single extra subroutine calls rather than all the startup and closedown
  2304. code being changed.
  2305.  
  2306. We include below simple source code for a program which:
  2307.  
  2308. 1. Has a simple structured "startup" word definition and a corresponding
  2309.    "closedown" routine: you can modify these for your own purposes and it
  2310.    would be a good idea to use them as a basis for all your early programs.
  2311.  
  2312. 2. Opens a custom screen
  2313.  
  2314. 3. Opens a window on the new screen
  2315.  
  2316. 4. Sets up graphic output to the new window and draws some graphics,
  2317.    including "graphic text"
  2318.  
  2319. 5. Sets up console text output in the new window and prints some text
  2320.  
  2321. 6. Sets up user input from the new window and waits for <SPACE> to
  2322.    be pressed.
  2323.  
  2324. 7. Uses an Amiga library call to show how it is done.
  2325.  
  2326. 8. Illustrates many of the concepts we have been discussing above......
  2327.  
  2328.  
  2329. You will be surprised, perhaps, to see how easy all this is, and certainly
  2330. you will be amazed how easy it is if you have used other Amiga programming
  2331. languages which require you to do an enormous amount more preparatory work.
  2332.  
  2333. **************************************************************************
  2334.  
  2335. Note:
  2336.  
  2337.   The following program is provided as a disk file called "Tutorial.Src".
  2338.  
  2339.   You can load this program into the HeliOS editor, as described for the
  2340.   small tutorial programs given earlier, then compile and run it.
  2341.  
  2342.   However, the code is included here so that you can read through it in
  2343.   the context of this tutorial.
  2344.  
  2345. **************************************************************************
  2346.  
  2347. --------------------------------------
  2348. A typical "universal" start up program
  2349. --------------------------------------
  2350.  
  2351. A typical start up program section might be as follows:
  2352.  
  2353.   FORGET **CORE**           \ Clear the user dictionary
  2354.  
  2355.   0. DVARIABLE SCREEN       \ New Screen handle storage variable
  2356.   0. DVARIABLE WINDOW       \ Window handle store
  2357.  
  2358.   0. DVARIABLE BITMAP       \ Variables to store useful values, which.
  2359.   0. DVARIABLE RASTPORT     \ are collected at startup time in case of
  2360.   0. DVARIABLE VIEW         \ the need to use them later in graphics
  2361.   0. DVARIABLE VIEWPORT     \ related functions.
  2362.  
  2363.  
  2364.   \ OPENSYSTEM - Opens a screen and a window and sets up Input/Output.
  2365.   \              Includes an example of a library call for you to see
  2366.   \              Returns "1" on the stack for success and "0" for failure
  2367.  
  2368.  
  2369.   : OPENSYSTEM              \ Start a colon definition, the new word is
  2370.                             \ called, appropriately, "OPENSYSTEM"
  2371.  
  2372.    TIMEOFF                  \ Disable the time display in the HeliOS screen
  2373.  
  2374.    0 HISTORY                \ Disable the line editor's circular buffer
  2375.  
  2376.    1 BAKSET                 \ Enable creation of Backup files on all disk
  2377.                             \ SAVE operations - a useful safety feature
  2378.  
  2379.    \ These are all "general purpose" startup operations often used
  2380.  
  2381.  
  2382.    1 STDSCREEN              \ Initialises a standard NewScreen structure
  2383.                             \   and sets Hires mode
  2384.  
  2385.    LIT$ $Tutorial Screen$   \ Specify the screen title bar text
  2386.  
  2387.    640 250                  \ Specify screen width and height
  2388.  
  2389.    3                        \ Depth of screen = number of bit planes
  2390.  
  2391.    OPENSCREEN               \ Open a screen using the initialised structure
  2392.  
  2393.    SCREEN D!                \ Store the screen handle/pointer 
  2394.  
  2395.    SCREEN D@                \ Get SCREEN 32-bit pointer onto stack
  2396.  
  2397.  
  2398.    D0>                      \ Test if SCREEN is greater than zero
  2399.                             \ This checks to see if screen opened OK
  2400.                             \ If SCREEN is zero we have trouble.......
  2401.  
  2402.    IF                       \ If SCREEN is not zero we are OK.........
  2403.  
  2404.      SCREEN D@              \ Get 32-bit pointer to screen
  2405.  
  2406.      44.                    \ Put double length number 44 on stack
  2407.  
  2408.      D+                     \ Add this to screen pointer to give
  2409.                             \ ViewPort pointer
  2410.  
  2411.      VIEWPORT D!            \ Store the ViewPort for the new screen
  2412.  
  2413.      STDWINDOW              \ Initialise a standard NewWindow structure
  2414.  
  2415.      HFWINDOW               \ Modify the standard window for it to appear
  2416.                             \ on the HeliOS Screen
  2417.  
  2418.      SCREEN D@              \ Get new screen again
  2419.  
  2420.      WINDOWSTRUCT           \ Returns 16-bit pointer to NewWindow
  2421.  
  2422.      30 +                   \ Add 30 to this
  2423.  
  2424.      D!                     \ Store screen pointer into NewWindow structure
  2425.  
  2426.      LIT$ $Tutorial Wind ow$ \ Title bar text for window
  2427.  
  2428.      0 12 640 238           \ Guess what....Window dimensions!
  2429.      3                      \ 3 BitPlanes
  2430.      0                      \ No SUPERBITMAP
  2431.      OPENWINDOW             \ Open the new window
  2432.  
  2433.      WINDOW D!              \ and store window pointer/handle
  2434.  
  2435.      WINDOW D@              \ Check if opened OK, like screen above
  2436.  
  2437.      D0>                    \ See "screen open" check above........
  2438.  
  2439.      IF
  2440.  
  2441.        WINDOW D@
  2442.        MAKEGFXWINDOW        \ Enable graphics in this window
  2443.  
  2444.        WINDOW D@
  2445.        MAKEOUTWINDOW        \ Enable text output to this window
  2446.  
  2447.        WINDOW D@
  2448.        MAKEINWINDOW         \ Enable user input from this window
  2449.  
  2450.        WINDOW D@            \ Get Window pointer
  2451.  
  2452.        50. D+               \ Add 50 to Window Pointer to get RastPort
  2453.  
  2454.        D@L                  \ Get RASTPORT pointer
  2455.  
  2456.        RASTPORT D!          \ Get Window's RastPort, and store it in
  2457.                             \ variable RASTPORT
  2458.  
  2459.        RASTPORT D@
  2460.        4. D+ D@L
  2461.        BITMAP D!            \ Get the bitmap from the stored RastPort
  2462.  
  2463.        INTUBASE             \ Put on the stack the 16-bit address
  2464.                             \  where the 32-bit pointer to Intuition
  2465.                             \  library base is stored
  2466.  
  2467.        -294                 \ Put on the stack the offset of the library
  2468.                             \  call "ViewAddress"
  2469.  
  2470.        LIBRARY              \ Call Intuition Library function to get
  2471.                             \ VIEW pointer
  2472.  
  2473.        D0RESULT             \ Get dummy register D0 value which is the
  2474.                             \ View address returned from the library call
  2475.  
  2476.        VIEW D!              \ Store pointer in variable VIEW
  2477.  
  2478.        1                    \ Put value "1" on stack to indicate that
  2479.                             \ everything opened OK
  2480.      ELSE
  2481.        0                    \ Put "0" on stack to indicate failure
  2482.      THEN
  2483.    ELSE
  2484.      0                      \ Put "0" on stack to indicate failure
  2485.    THEN
  2486.    ;                        \ End of Colon Definition
  2487.  
  2488.  
  2489.   \ In a similar manner we have a defined a HeliOS word for the related
  2490.   \ close down routine.
  2491.  
  2492.  
  2493.    : CLOSESYSTEM            \ Start the colon definition
  2494.  
  2495.    FORTHINWINDOW            \ Redirect the input and output from
  2496.    FORTHOUTWINDOW           \ program's window back to the HeliOS
  2497.    FWINDOW MAKEGFXWINDOW    \ interactive environment
  2498.  
  2499.    WINDOW D@                \ Get contents of window handle store
  2500.    DFLAG                    \ Check and if Non-Zero put 1 on stack else
  2501.                             \ put 0 on stack above window handle
  2502.  
  2503.    IF                       \ If window is open, ie handle is non zero
  2504.      CLOSEWINDOW            \ Close it
  2505.      WINDOW D0!             \ then set store to zero
  2506.    ELSE
  2507.       DDROP                 \ else cleanup stack (drop window handle)
  2508.    THEN                     \ end of If/Then structure
  2509.  
  2510.    SCREEN D@                \ Look at screen handle
  2511.    DFLAG                    \ Check and if Non-Zero put 1 on stack else
  2512.                             \ put 0 on stack above screen handle
  2513.    IF                       \ If it is open......
  2514.      CLOSESCREEN
  2515.      SCREEN D0!
  2516.    ELSE
  2517.      DDROP
  2518.    THEN
  2519.  
  2520.    TIMEON                   \ Enable time display for the
  2521.                             \ HeliOS screen before exiting
  2522.    ;                        \ End of colon definition
  2523.  
  2524.  
  2525.     \ Now we can use these functions in a small program:
  2526.  
  2527.  
  2528.   : TUTORIALPROGRAM
  2529.  
  2530.   OPENSYSTEM                        \ Open environment, returning 1 or 0
  2531.                                     \ indicating success or failure
  2532.  
  2533.   IF                                \ If 1 is returned, for "success"
  2534.  
  2535.     1 GFXSETOPEN                    \ Set graphics outline pen colour to 1
  2536.  
  2537.     1 GFXOUTLINE                    \ Switch on graphics OUTLINE mode
  2538.  
  2539.     2 GFXSETAPEN                    \ Set graphics pen to "2" for circle
  2540.  
  2541.     400 160 80 40                   \ Circle coordinates
  2542.  
  2543.     GFXAREAELLIPSE                  \ Draw circle into off screen buffer
  2544.  
  2545.     GFXAREAEND                      \ Render circle to screen
  2546.  
  2547.     0 GFXOUTLINE                    \ Switch off graphics OUTLINE mode
  2548.  
  2549.     3 GFXSETAPEN                    \ Set graphics pen to "3" for text
  2550.  
  2551.     100 200 GFXMOVE                 \ Set graphics pen position
  2552.  
  2553.     LIT$ $This is graphic text$     \ Text string
  2554.  
  2555.     COUNT                           \ Get text start and length
  2556.  
  2557.     GFXTEXT                         \ Output text
  2558.  
  2559.  
  2560.     20 10 CURPUT                         \ Place cursor
  2561.  
  2562.     ." Hello....Press <SPACE> to exit!"  \ Some console text output
  2563.  
  2564.  
  2565.     BEGIN                    \ Start a BEGIN/UNTIL construct
  2566.  
  2567.       KEY                    \ Wait for a keypress
  2568.  
  2569.       32                     \ ASCII code for <SPACE> is 32
  2570.  
  2571.       =                      \ See if KEY value = 32
  2572.  
  2573.     UNTIL                    \ Loop until result is TRUE
  2574.  
  2575.   THEN
  2576.  
  2577.   CLOSESYSTEM                \ Close environment
  2578.   ;
  2579.  
  2580.   TUTORIALPROGRAM            \ Actually execute the new "program" word.
  2581.  
  2582.  \ End of program
  2583.  
  2584.  
  2585. *************************************************************************
  2586.  
  2587. -------------------------------
  2588. A few simple hints on debugging
  2589. -------------------------------
  2590.  
  2591. Debugging consists mainly of locating the area where a problem occurs.
  2592.  
  2593. Doing this sometimes requires additional information about program
  2594. execution, and in these cases the custom HeliOS debugger is very useful.
  2595.  
  2596. Beware, however, of the common mistake of using a debugger to generate
  2597. a lot of extra information which in fact confuses the issue and makes
  2598. the task of debugging harder than it need be.
  2599.  
  2600. Often the simple use of output statements within a program, along with
  2601. careful inspection and analysis of the code, is all that is required.
  2602.  
  2603. HeliOS has a very powerful user-configurable debugger, but for most
  2604. debugging you should never need to use it!  The following hints should
  2605. be taken as general programming guidelines, and for detailed discussion
  2606. of the HeliOS debugger you should refer to the debugger documentation.
  2607.  
  2608. There are a few simple techniques which, combined with sensible programming
  2609. strategies (for example, do not write 200k of source code altogether with
  2610. no testing then expect it to work instantly...), will enable you to debug
  2611. code very simply.
  2612.  
  2613. When a bug occurs the program will often (probably!) crash.
  2614.  
  2615. The best simple debugging technique is to put a repetitive debug line
  2616. into the code up to and including the crash point.
  2617.  
  2618. This line should display the stack status and wait for the space bar
  2619. to be pressed.  Something like the following will do nicely:
  2620.  
  2621.  ." Now at line xxx. Stack reads: " .S ." <SPACE> to continue" WAITSPACE CR
  2622.  
  2623.  
  2624. A few of these lines included in your code will give you a sequential
  2625. talk-through until the crash point is reached.
  2626.  
  2627. Start with the high level code first and then work into your subroutines:
  2628. in this way you can home in on the actual fault.  It is good practice to
  2629. check each subroutine thoroughly as it is completed, but nevertheless the
  2630. most unexpected results can occur when even apparantly sound subroutines
  2631. are used together in complex ways.
  2632.  
  2633. The stack status message debug line suggested above will probably mess up
  2634. your program's screen display, but that does not really matter in a debug
  2635. operation.
  2636.  
  2637. Always check for stack aberrations first: be aware of what the stack should
  2638. be reading and check your debug stack readouts scrupulously.
  2639.  
  2640. If you like, include DUMP commands in your debug instructions to dump areas
  2641. of memory for careful scrutiny.
  2642.  
  2643. There are so many ways for code to fail it is impossible to cover all the
  2644. aspects of debugging: also debugging is a very intuitive thing and everyone
  2645. has very personal preferences.
  2646.  
  2647. The main thing is to never assume ANYTHING to be OK without double checking,
  2648. and be prepared to be patient and check EVERYTHING relating to your problem
  2649. with an open mind.
  2650.  
  2651. Check your stack dumps minutely, dump and also check any areas of memory
  2652. you think may be suspect, check variable values by including them in your
  2653. debug lines where appropriate.
  2654.  
  2655. One big source of trouble is using address pointers which should really be
  2656. pointing at something useful like a screen structure address, but actually
  2657. contain zero.  For example, in our little program above, we checked that
  2658. the screen had opened OK and that its returned value was not null. If we
  2659. did not do this and then went on to use the screen handle, not realising
  2660. that it was zero, terrible things would happen.....
  2661.  
  2662. This sort of mistake is quite easy to make in more complex code.
  2663.  
  2664. A golden rule on a multitasking machine like the Amiga is never to assume
  2665. that an allocation or opening routine must always succeed.
  2666.  
  2667. Always check to see if everything has opened correctly, and always take care
  2668. to initialise all fields of data structures correctly.
  2669.  
  2670. *************************************************************************
  2671.  
  2672. -------------------
  2673. Additional reading?
  2674. -------------------
  2675.  
  2676. Perhaps you are wondering whether HeliOS is similar to any other languages
  2677. and whether you can get any books to help you learn to program?
  2678.  
  2679. It is always useful to read a variety of documentary material when you are
  2680. learning a new programming language because different authors will often
  2681. give you very different and valuable insights.
  2682.  
  2683. HeliOS is a threaded interpretive language derived from Forth, so many of 
  2684. its simplest commands are Forth oriented.  A basic understanding of Forth
  2685. (which is a much smaller language in scope than HeliOS) will certainly help
  2686. you get started with HeliOS, and if you have access to any Forth textbooks
  2687. these will give you a good idea of the way HeliOS programs are structured.
  2688.  
  2689. Forth text books will provide you with many helpful insights if you want
  2690. to read them as background information: however, you should beware of taking
  2691. the analogy between Forth and HeliOS too far.  The fact is that superficial
  2692. similarity between the languages can be deceptive, so take care.....
  2693.  
  2694. As a Forth instructional text we advise you to search out Leo Brodie's
  2695. excellent text "Starting Forth", published by Prentice Hall in paperback.
  2696. The same author and publisher also produce a book called Thinking Forth,
  2697. which is well worth reading for its insights into clever Forth programming
  2698. strategy.
  2699.  
  2700. You will certainly need to study specialised texts on the Amiga if you
  2701. want to get the best out of HeliOS because HeliOS, like "C", makes use of
  2702. the Amiga operating system and also allows direct Amiga hardware control.
  2703.  
  2704. The Addison-Wesley Amiga manuals are an excellent investment if you are
  2705. serious about Amiga programming, and Compute Books' "Mapping the Amiga"
  2706. is an extremely useful reference text.
  2707.  
  2708. HeliOS can supply an excellent comprehensive set of example programs on
  2709. all HeliOS commands written by Sebastien Veyrin-Forrer.  These short
  2710. example programs detail the use of every word in the HeliOS vocabulary.
  2711.  
  2712. ----------------------------------------------------------------------
  2713. End
  2714. ----------------------------------------------------------------------
  2715.